14

如果将 Windows 窗体控件的 Visible 属性设置为 true,则如果控件的任何父窗口被隐藏,该属性仍会返回 false。如果父窗口被隐藏,有没有办法获得控件的真实、底层可见性标志?

4

4 回答 4

15

好吧,常规实现确实会检查控制堆栈,以确保所有父级都是可见的。我知道的唯一规避方法是用反射作弊,并要求GetState(2),但这很脆弱:

    // dodgy; not recommended
    Panel query;
    Form form = new Form
    {
        Controls = {
            new Panel {
                Visible = false,
                Controls = {
                    (query = new Panel {Visible = true})
                }
            }
        }
    };
    form.Show();

    // this is the dodgy bit...
    bool visible = (bool)typeof(Control)
        .GetMethod("GetState", BindingFlags.Instance | BindingFlags.NonPublic)
        .Invoke(query, new object[] { 2 });
于 2008-12-24T17:36:09.920 回答
2

我所做的是暂时从其父控件中删除按钮以检查其 Visible 值,然后重新添加到父控件。

如果需要,您可以跟踪子索引以将其重新添加到正确的索引中。

于 2014-02-14T11:28:06.633 回答
0

我对从“ToolStripItem”基类派生的类有同样的问题。所以我使用 Available 属性值来检查项目是否会显示。问题解决了。样本:

ToolStripItem curItm = menuStrip1.Items[i] as ToolStripItem;
if(curItm is ToolStripItem && curItm.Available) DoAnyThing();

在此示例中,“curItm”是 ToolStripItem 派生类的一个实例。

.Net 控件中依赖于父容器的 Visible/Enabled 的 Visible/Enabled 属性的这个问题必须由 .Net 团队解决。我在自己的类中创建了一个名为 IsVisible/IsEnabled 的服装属性,该属性返回为 Visible/Enabled 属性分配的值,而不是依赖于父容器的值。

于 2016-10-22T10:59:02.087 回答
-1

不依赖于反射的一个选项是通过控件层次结构的父级递归查找 Visible 设置为 false 的父级。

编辑:请参阅注释以了解代码的重要性。

var frm2 = new Form {Text = "Form2"};
var lbl = new Label {Visible = true};
frm2.Controls.Add(lbl);
frm2.Show();

var frm1 = new Form {Text = "Form1"};
var lblVis = new Label { Text = lbl.Visible.ToString(), Left = 10, Top = 10};
lbl.VisibleChanged += (sender, args) => MessageBox.Show("Label Visible changed");
var btnShow = new Button {Text = "Show", Left = 10, Top = lblVis.Bottom + 10};
btnShow.Click += (sender, args) =>
                    {
                        frm2.Visible = true;
                        lblVis.Text = lbl.Visible.ToString();
                        };
var btnHide = new Button {Text = "Hide", Left = 10, Top = btnShow.Bottom + 10};
btnHide.Click += (sender, args) =>
                    {
                        frm2.Visible = false;
                        lblVis.Text = lbl.Visible.ToString();
                    };

frm1.Controls.AddRange(new Control[] {lblVis, btnShow, btnHide});

Application.Run(frm1);

于 2008-12-24T17:48:55.153 回答