Как предотвратить вертикальную полосу прокрутки от пробела в элементе управления, вызывая горизонтальную полосу прокрутки?
У меня есть настраиваемый элемент управления с встроенным FlowLayoutPanel
, к которому я добавляю элементы (другие настраиваемые элементы управления). В событии компоновки FlowLayoutPanel
меняю размеры всех элементов управления в FlowLayoutPanel
на размер содержащего FlowLayoutPanel
.
Это нормально, пока не потребуется вертикальная полоса прокрутки (AutoScroll = True
), занимая пространство внутри FLpanel
, вызывая горизонтальную полосу прокрутки.
Таблетка, которую вы видите, представляет собой случайный текст заполнителя, который я генерирую в конструкторе элемента.
Я хотел бы предотвратить это:
![nasty scrollbar effect]()
Я попытался добавить вертикальный элемент управления прокруткой в usercontrol и сделать FlowLayoutPanel.VertScroll.Value=sender.value
в событии Scroll
: он работает, но делает фактические вертикальные и горизонтальные полосы прокрутки мерцающими (появляющимися и исчезающими) при перемещении полосы прокрутки контроль.
Я действительно не знаю, есть ли какое-то свойство, чтобы сделать панель прокрутки внешней по отношению к содержимому элемента управления FlowLayoutPanel
.
Я делаю это в VB.Net, но ответы на С# прекрасны (поскольку это в основном тот же синтаксис, по крайней мере, при работе с элементами управления и пользовательским интерфейсом).
Изменить
Я забыл упомянуть, что у меня есть WrapContents=false
и AutoScroll=true
в FlowLayoutPanel
.
Кроме того, если вы считаете, что этот дизайн знаком: это идеальная копия экрана списка Opera M2, идеально подходящая для пикселя.
Обновление 1
После ваших комментариев я придумал следующее:
Public Class FlowListPanel ' The user control
Private Sub Me_Load(sender As Object, e As EventArgs) Handles Me.Load
FL_Panel.AutoScroll = True ' FL_Panel is the FlowLayoutPanel
FL_Panel.WrapContents = False
FL_Panel.Dock = System.Windows.Forms.DockStyle.Fill
FL_Panel.FlowDirection = System.Windows.Forms.FlowDirection.TopDown
FL_Panel.Margin = New System.Windows.Forms.Padding(0)
End Sub
Sub AddItem(c As Control)
FL_Panel.Controls.Add(c)
ReorderControls()
End Sub
Private Sub FLP_CSC(sender As Object, e As EventArgs) Handles FL_Panel.ClientSizeChanged
ReorderControls()
End Sub
Sub ReorderControls()
For Each ctrl In FL_Panel.Controls
ctrl.Width = FL_Panel.ClientSize.Width
Next
End Sub
Private Sub FL_Panel_L(sender As Object, e As LayoutEventArgs) Handles FL_Panel.Layout
ReorderControls()
End Sub
End Class
Кажется, что это работает, но возникает проблема с появлением горизонтальной полосы прокрутки, когда достигается критическая точка, в которой появляется вертикальная полоса прокрутки.
После добавления другого элемента горизонтальная полоса прокрутки исчезает.
Кроме того, я думал, что проблема может быть вызвана тем, что ReorderControls
не вызван, поэтому я сделал кнопку, чтобы вызвать его, но ничего не изменилось.
Эта проблема отсутствует при удалении элементов (но это происходит только при добавлении).
Это также происходит при изменении размера окна и появлении вертикальной полосы прокрутки.
Как я покажу ниже, после добавления нового элемента он отлично работает:
![nasty scrollbar effect returns]()
Обновление 2
Я следил за советом Plutonix (адаптировав код из своего другого ответа), и поэтому я применил некоторые изменения к sub ReorderControls
следующим образом:
Sub ReorderControls()
Dim HScrollVis As Boolean = NativeMethods.IsHScrollVisible(FL_Panel)
If HScrollVis Then ' HScroll visible -> kill it with fire!
NativeMethods.ShowHideScrollBar(FL_Panel,
NativeMethods.SBOrientation.SB_HORZ,
False)
Return ' as it works anyway...
End If
For Each ctrl In FL_Panel.Controls
ctrl.Width = FL_Panel.ClientSize.Width
Next
End Sub
Теперь горизонтальная полоса прокрутки мерцает один раз, а не остается там, когда появляется вертикальная.
Мне нравятся gif, так что вот текущий эффект:
![nasty scrollbar effect: a new hope]()
Как вы, вероятно, не видите (из-за низкой частоты кадров в gif), горизонтальная панель, вероятно, заметна только для тех, кто ищет ее, в течение секунды.
Я считаю, что проблема 80% решена и будет двигаться дальше. Если я или кто-то придумаю что-то окончательное, я немедленно приму ответ.
Ответы
Ответ 1
Вот альтернативный подход, который дает вам желаемый результат. Если он не отвечает напрямую на ваш вопрос, но, на мой взгляд, если вам нужно возиться с тем, как работают элементы управления, чтобы получить желаемое решение, вы не используете правильные элементы управления.
Вместо того, чтобы добавлять свои элементы управления непосредственно в FowLayoutPanel,
Использовать стандартный объект Panel, содержащий таблицу TableLayoutPanel.
Задайте свойства панели...
AutoScroll = True
Задайте свойства TableLayoutPanel для
Dock = Top
Autosize = True, GrowAndSHrink
Начните с одной ячейки в TableLayoutPanel..
Теперь добавьте элементы управления в TableLayoutPanel...
например.
Dim CTRL As New Your_User_Control
TableLayoutPanel1.Controls.Add(CTRL)
CTRL.Dock = DockStyle.Top
Когда появится полоса прокрутки, TableLAyoutPanel будет уменьшаться горизонтально на соответствующую сумму, и все содержащиеся элементы управления также будут автоматически уменьшаться.
Ответ 2
Просто убедитесь, что вы инициализируете его следующими свойствами:
this.WrapContents = false;
this.AutoScroll = true;
Вам также необходимо убедиться, что элементы управления, которые вы добавляете к нему, имеют максимальную ширину ширины управления минус ширина полосы прокрутки.
Это должно сделать это, хотя.
Edit:
Я получил это решение из одного из моих пользовательских элементов управления. Похоже, он очень похож на этот пост, но, возможно, я получил его оттуда, я не могу вспомнить. Сообщение, связанное на всякий случай.
Изменить 2:
Поскольку вы уже устанавливаете эти свойства и просматриваете изображение, вам просто нужно сделать элементы управления, которые вы добавляете к узлу FlowPanel, или FlowPanel шире.
В принципе, вам нужно просто разрешить пространство, в котором будет отображаться полоса прокрутки. Вы можете определить, видимо ли это, и заставить внутренние элементы управления соответственно обновить свой макет, если вы действительно хотите использовать всю ширину в любое время.