如何避免在显示和隐藏控件时更改控件的 z 顺序?

发布于 2024-11-03 07:50:41 字数 426 浏览 4 评论 0原文

我有一个带有一些控件(面板、组框等)的表单,它们都设置了 control.Dock = DockStyle.Top 。根据表单上组合框的选定值,只有其中一些面板应同时可见(因为隐藏的面板不适用于选定的选项)。对接是为了让UI显得更加简洁。

每当组合框选择更改以及窗体的 Shown 事件时,这些面板的可见属性都会更改(因为当第一次显示窗体并且组合框选择尚未更改时,并非所有面板都应该可见)。

现在的问题是,当我关闭表单(因为它是模式对话框,因此不会被破坏)时,稍后重新打开并更改组合框选择顶部面板的显示顺序表格的内容已更改。直到表单关闭一次后才会发生这种情况。我知道停靠控件的显示顺序与父控件的 ControlCollection 中这些控件的顺序相关联。这也决定了控件的 z 顺序,因此是问题的标题。

是什么导致控制顺序发生变化以及如何避免它?

I have got a Form with some Controls (Panels, Group Boxes etc.) on it which all have control.Dock = DockStyle.Top set. Based on the selected value of a ComboBox on the Form only some of these Panels should be visible at the same time (because the hidden ones don't apply for the selected option). The docking is to make the UI appear more compact.

The Visible properties of those Panels are changed whenever the ComboBox selection changes and on the Form's Shown event (because not all Panels should be visible when the Form is shown for the first time and the ComboBox selection has not yet changed).

Now, the problem is, that when I close the Form (as it is a modal dialog, it is not destroyed), reopen it later and change the ComboBox selection the display order of the Panels at the top of the Form has changed. It does not happen until the Form was closed one time. I know that the display order of docked Controls is linked to the order of these Controls in the parent control's ControlCollection. This also determines the z-Order of the Controls, hence the question's title.

What causes the Controls order to change and how to avoid it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

看轻我的陪伴 2024-11-10 07:50:41

经过更多调试后我发现重新排序
与句柄创建有关。

当表单第一次打开时,所有面板都是可见的(因为我没有
在设计时更改)并且所有句柄都会立即创建,
在一些被 Form.Shown 事件处理程序隐藏之前。当
表单关闭,句柄丢失。但是,如果表格显示
第二次,只有面板的手柄已经被
表单关闭时可见的内容会立即重新创建。一旦控件变得可见,每个句柄就会被创建(正如 MSDN 指出的那样)
出)但显然现在显示控件的顺序很重要
因为 Controls 可以在父级的 ControlCollection 中移动
创建句柄后。

原来,当表格第二次展示时,之前
显示某个Panel(此处为PanelToBecomeVisible)的控制顺序
was:

0    Panel1
1  h InitiallyVisibleButLaterHiddenPanel
2    Panel2
3    PanelToBecomeVisible
4 vh AlwaysVisibleTopMostPanel

其中 v 表示可见,h 表示 IsHandleCreated 为 true。后
PanelToBecomeVisible.Visible = True ControlCollection 看起来像
this:

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

After more debugging I found out that the reordering
is related to Handle creation.

When the Form is first opened, all Panels are visible (as I didn't
change that at design time) and all Handles are created immediately,
before some are hidden by the Form.Shown event handler. When the
Form is closed, the handles are lost. However, if the Form is shown
for the second time, only the handles of the Panels that have been
visible when the Form was closed are recreated immediately. Each handle is created once the Control becomes visible (as MSDN points
out) but apparently now the order of showing the Controls is important
because the Controls can be moved in the parent's ControlCollection
upon handle creation.

It turned out that when the Form was shown the second time, before
showing a certain Panel (here PanelToBecomeVisible) the Control order
was:

0    Panel1
1  h InitiallyVisibleButLaterHiddenPanel
2    Panel2
3    PanelToBecomeVisible
4 vh AlwaysVisibleTopMostPanel

where v means visible and h that IsHandleCreated is true. After
PanelToBecomeVisible.Visible = True the ControlCollection looks like
this:

0    Panel1
1  h InitiallyVisibleButLaterHiddenPanel
2 vh PanelToBecomeVisible
3    Panel2
4 vh AlwaysVisibleTopMostPanel

And if Panel2 becomes visible later, it will subsequently have swapped
positions with PanelToBecomeVisible.

Thus, one solution is to make sure all handles are created early even
if the Panels are not visible yet. This can be achieved by accessing
the Handle property of every Control in question like this, e. g.:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文