【发布时间】:2019-04-30 12:45:01
【问题描述】:
快速笔记
我已尝试尽可能详尽地回答我的问题,但您可能仍需要进一步澄清;如果发生这种情况,请随时评论您的疑虑,我会更新帖子以尽我所能回答。
昨天我在表单上切换控件时遇到了一个相当奇怪的问题。我在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 (TrackBar)
- 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事件将引发。
问题
可能会发生什么使这种奇怪的行为成为可能?
【问题讨论】:
-
你确定
timeSlider在pTimePanel里面,而不是躲在timeSlider后面吗? -
对于这类问题,我经常发现尝试在一个非常简单的新项目中重新创建它会有所帮助。要么从零开始构建真正的代码,要么从真正的代码的副本开始并删减内容。如果你能做到这一点,并发布示例,人们就会为你调试它。
-
@RobinBennett 这是一个非常好的主意,我考虑过重建表单以确保一切都在它应该在的位置,然后再试一次,但我想我会看看是否有其他人遇到过一个类似的问题,因为我从未见过更简单的表格。我在想,也许我只是按错误的顺序添加了一些东西。
-
可以切换父控件的可见性来切换其子控件的可见性吗?在这种情况下,我不会切换,而是将可见性显式设置为
true或false。 -
也许不递归地应用切换会有所帮助,而是只切换顶级控件的可见性,
loadingContainer除外。我也会测试c == loadingContainer。这比依赖名称更安全。
标签: c# winforms controls toggle visibility