Как избежать изменения z-порядка элементов управления при их отображении и скрытии?
У меня есть форма с некоторыми элементами управления (панели, групповые блоки и т. Д.), Которые все имеют control.Dock = DockStyle.Top
задавать. На основании выбранного значения ComboBox в форме, только некоторые из этих панелей должны быть видны одновременно (потому что скрытые не применяются для выбранной опции). Стыковка должна сделать интерфейс более компактным.
Видимые свойства этих панелей изменяются всякий раз, когда изменяется выбор ComboBox и в событии "Показано" формы (поскольку не все панели должны быть видны, когда форма отображается в первый раз, а выбор ComboBox еще не изменился).
Теперь проблема в том, что когда я закрываю форму (поскольку это модальное диалоговое окно, она не уничтожается), открываю ее позже и изменяю выбор ComboBox, порядок отображения панелей в верхней части формы изменился. Это не происходит, пока форма не была закрыта один раз. Я знаю, что порядок отображения закрепленных элементов управления связан с порядком этих элементов управления в ControlCollection родительского элемента управления. Это также определяет z-порядок элементов управления, отсюда и название вопроса.
Что вызывает изменение порядка управления и как его избежать?
1 ответ
После дополнительной отладки я обнаружил, что переупорядочение связано с созданием дескриптора.
При первом открытии формы все панели становятся видимыми (как я не менял во время разработки), и все дескрипторы создаются немедленно, прежде чем некоторые из них будут скрыты Form.Shown
обработчик события. Когда форма закрыта, ручки теряются. Однако, если форма отображается во второй раз, немедленно создаются только те дескрипторы панелей, которые были видны при закрытии формы. Каждый дескриптор создается после того, как элемент управления становится видимым (как указывает MSDN), но теперь очевидно, что порядок отображения элементов управления важен, поскольку элементы управления могут быть перемещены в родительскую ControlCollection при создании дескриптора.
Оказалось, что когда Форма была показана во второй раз, перед тем, как показывать определенную Панель (здесь PanelToBecomeVisible), порядок управления был:
0 Panel1
1 h InitiallyVisibleButLaterHiddenPanel
2 Panel2
3 PanelToBecomeVisible
4 vh AlwaysVisibleTopMostPanel
где v означает видимый, а h, что IsHandleCreated является истиной. ПослеPanelToBecomeVisible.Visible = True
ControlCollection выглядит так:
0 Panel1
1 h InitiallyVisibleButLaterHiddenPanel
2 vh PanelToBecomeVisible
3 Panel2
4 vh AlwaysVisibleTopMostPanel
И если Panel2 станет видимой позже, она впоследствии поменяется местами с PanelToBecomeVisible.
Таким образом, одним из решений является обеспечение того, чтобы все маркеры были созданы заранее, даже если панели еще не видны. Это может быть достигнуто путем доступа к Handle
свойство каждого рассматриваемого элемента управления, например, например:
Private Sub Form_Shown(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Shown
Dim h As IntPtr
For Each ctrl As Control In ParentControl.Controls
h = ctrl.Handle
Next
End Sub