.net 如何获得;“真正的”;有形财产的价值?
如果将Windows窗体控件的Visible属性设置为true,则如果该控件的任何父窗口被隐藏,该属性仍将返回false。在父窗口被隐藏的情况下,是否有方法获得控件的真实的底层可见性标志?好的,常规实现会检查控件堆栈,以确保所有父窗口都可见。我所知道的避免这种情况的唯一方法是用反射欺骗,并要求.net 如何获得;“真正的”;有形财产的价值?,.net,winforms,visible,.net,Winforms,Visible,如果将Windows窗体控件的Visible属性设置为true,则如果该控件的任何父窗口被隐藏,该属性仍将返回false。在父窗口被隐藏的情况下,是否有方法获得控件的真实的底层可见性标志?好的,常规实现会检查控件堆栈,以确保所有父窗口都可见。我所知道的避免这种情况的唯一方法是用反射欺骗,并要求GetState(2),但这很脆弱: // dodgy; not recommended Panel query; Form form = new Form {
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 });
一个不依赖反射的选项是通过控件层次结构的父级递归,查找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);
var frm2=新表格{Text=“Form2”};
var lbl=新标签{Visible=true};
frm2.控件.添加(lbl);
frm2.Show();
var frm1=新表格{Text=“Form1”};
var lblVis=new Label{Text=lbl.Visible.ToString(),Left=10,Top=10};
lbl.VisibleChanged+=(发送方,参数)=>MessageBox.Show(“标签可见已更改”);
var btnShow=new按钮{Text=“Show”,Left=10,Top=lblVis.Bottom+10};
b显示。单击+=(发件人,参数)=>
{
frm2.可见=真实;
lblVis.Text=lbl.Visible.ToString();
};
var btnHide=new按钮{Text=“Hide”,Left=10,Top=btnShow.Bottom+10};
btnHide.单击+=(发件人,参数)=>
{
frm2.可见=假;
lblVis.Text=lbl.Visible.ToString();
};
frm1.Controls.AddRange(新控件[]{lblVis,btnShow,btnHide});
应用程序运行(frm1);
我所做的是从父控件中临时删除按钮以检查其可见值,然后重新添加到父控件
如果需要,可以跟踪子索引,将其重新添加到正确的索引中。对于从“ToolStripItem”基类派生的类,我也有同样的问题。所以我使用可用属性值来检查项目是否会显示。问题解决了。样本:
ToolStripItem curItm = menuStrip1.Items[i] as ToolStripItem;
if(curItm is ToolStripItem && curItm.Available) DoAnyThing();
在此示例中,“curItm”是ToolStripItem派生类的实例
.Net控件中依赖父容器的可见/启用属性的可见/启用属性的问题必须由.Net团队解决。
我在自己的类中创建了一个名为IsVisible/IsEnabled的costure属性,该属性返回可见/启用属性的赋值,而不是依赖于父容器的值。但这不会告诉您原始属性是真是假;如果没有不可见的父项,您可以(可能)信任.Visible,但如果有,您不知道控件是否(本地)可见=true或Visible=false您必须同时查看这两者,因此,如果当前可见,则查找任何为false的父项将意味着当前不可见。但如果任何父项不可见,则visible将永远不会返回true;这就是问题所在:框架已经对此进行了检查。我认为OP想知道本地控件是否认为它是可见的,也就是说,如果所有父级都是可见的,它也会是可见的吗?你不能仅仅通过Visible找到它。有趣的是,我没有看到它的变化,因为我是基于VisibleChanged事件的,当父控件Visible属性发生变化时,该事件没有触发。我猜这是一个泄漏的抽象,我将编辑文章以放置一些代码来显示我的意思。当父对象被隐藏时,不会触发子对象的VisibleChanged,但当父对象被设置为可见时,则会触发。2是什么?有常数或枚举可以替代吗?@Jon,是的,有-但它本身是内部的,所以你必须使用更多的反射来获得它-但它是可见的。