递归切换可见性后控件不可见?
Control not visible after toggling visibility recursively?
快速说明
我已尝试尽可能详尽地回答我的问题,但您可能仍需要进一步说明;如果发生这种情况,请随时评论您的疑虑,我会更新 post 以尽我所能回答他们。
我昨天在切换表单上的控件时遇到了一个相当奇怪的问题。我在 FormShown
上有一段加载时间,除加载显示外的所有控件都应隐藏。切换用于关闭除加载显示以外的所有内容的可见性,但是当加载完成时,只有部分控件可见。
我逐步完成了将所有内容恢复为可见的代码,并确保所有内容确实都设置为 Visible = true
。我认为这可能与控件上的 Dock
属性 有关,或者可能与 TabIndex
或类似的东西有关,但我无法追踪潜在的问题。
这是我用来切换控件可见性的代码:
private void ToggleAllControlVisibility() {
foreach (Control c in Controls)
ToggleControlVisibility(c);
}
private void ToggleControlVisibility(Control c) {
if (c.Name == "loadingContainer")
return;
if (!(c is SplitContainer || c is SplitterPanel))
c.Visible = !c.Visible;
foreach (Control child in c.Controls)
ToggleControlVisibility(child);
}
这是一个递归切换,其中所有子控件也被切换。 ToggleAllControlVisibility
方法在加载开始前调用,加载完成后再次调用。
更详细的了解
既然您知道了问题所在,我知道有一些特定的控件不会显示(至少它们应该显示的方式)。以下面的控件树为例:
- pTimePanel(面板)
- timeSlider(轨迹栏)
- lblStartTime(标签)
- lblStopTime(标签)
在上面的控件中,只有 pTimePanel
实际上显示在前景中。我相信它的子控件可能以某种方式显示在它后面,因为当我逐步执行代码并到达 lblStartTime
控件时,我可以简要地看到标签的轮廓(无内容),然后当它移动到下一个时控制它消失了。 timeSlider
控件似乎没有显示相同的行为,但它确实返回到 Visible = true
。
从窗体到上述控件(具有停靠属性)的完整树如下:
splitContainer : Dock-Fill
panel1 (SplitterPanel)
loadingPanel (Panel) : Dock-Fill
pTimePanel (Panel) : Dock-Bottom
pTimeLabels (Panel) : Dock-Bottom
lblStartTime (Label) : Dock-Left
lblStopTime (Label) : Dock-Right
timeSlider (TrackBar) : Dock-Fill
备注
其中一些可能不如其他有用,但当我想到可能有助于澄清正在发生的事情时,我将在此处添加它们。
- 在任一方向切换可见性时,都会引发
loadingPanel
上的 Resize
事件。
问题
可能会发生什么使这种奇怪的行为成为可能?
原来这与控件添加到窗体的顺序有关。由于前一段时间的一些复制和粘贴控制,事情以不正确的顺序结束。我必须从头开始重建表格才能使任何切换真正起作用。重建表单后,所有可用的切换选项都开始按照我预期的方式工作。
快速说明
我已尝试尽可能详尽地回答我的问题,但您可能仍需要进一步说明;如果发生这种情况,请随时评论您的疑虑,我会更新 post 以尽我所能回答他们。
我昨天在切换表单上的控件时遇到了一个相当奇怪的问题。我在 FormShown
上有一段加载时间,除加载显示外的所有控件都应隐藏。切换用于关闭除加载显示以外的所有内容的可见性,但是当加载完成时,只有部分控件可见。
我逐步完成了将所有内容恢复为可见的代码,并确保所有内容确实都设置为 Visible = true
。我认为这可能与控件上的 Dock
属性 有关,或者可能与 TabIndex
或类似的东西有关,但我无法追踪潜在的问题。
这是我用来切换控件可见性的代码:
private void ToggleAllControlVisibility() {
foreach (Control c in Controls)
ToggleControlVisibility(c);
}
private void ToggleControlVisibility(Control c) {
if (c.Name == "loadingContainer")
return;
if (!(c is SplitContainer || c is SplitterPanel))
c.Visible = !c.Visible;
foreach (Control child in c.Controls)
ToggleControlVisibility(child);
}
这是一个递归切换,其中所有子控件也被切换。 ToggleAllControlVisibility
方法在加载开始前调用,加载完成后再次调用。
更详细的了解
既然您知道了问题所在,我知道有一些特定的控件不会显示(至少它们应该显示的方式)。以下面的控件树为例:
- pTimePanel(面板)
- timeSlider(轨迹栏)
- lblStartTime(标签)
- lblStopTime(标签)
在上面的控件中,只有 pTimePanel
实际上显示在前景中。我相信它的子控件可能以某种方式显示在它后面,因为当我逐步执行代码并到达 lblStartTime
控件时,我可以简要地看到标签的轮廓(无内容),然后当它移动到下一个时控制它消失了。 timeSlider
控件似乎没有显示相同的行为,但它确实返回到 Visible = true
。
从窗体到上述控件(具有停靠属性)的完整树如下:
splitContainer : Dock-Fill
panel1 (SplitterPanel)
loadingPanel (Panel) : Dock-Fill
pTimePanel (Panel) : Dock-Bottom
pTimeLabels (Panel) : Dock-Bottom
lblStartTime (Label) : Dock-Left
lblStopTime (Label) : Dock-Right
timeSlider (TrackBar) : Dock-Fill
备注
其中一些可能不如其他有用,但当我想到可能有助于澄清正在发生的事情时,我将在此处添加它们。
- 在任一方向切换可见性时,都会引发
loadingPanel
上的Resize
事件。
问题
可能会发生什么使这种奇怪的行为成为可能?
原来这与控件添加到窗体的顺序有关。由于前一段时间的一些复制和粘贴控制,事情以不正确的顺序结束。我必须从头开始重建表格才能使任何切换真正起作用。重建表单后,所有可用的切换选项都开始按照我预期的方式工作。