Если вы установите для свойства Visible элемента управления Windows Forms значение true, это свойство все равно возвращает false, если какое-либо из окон родительского контроля скрыто. Есть ли способ получить истинный, базовый флаг видимости элемента управления в случае скрытия родительского окна?
Как получить "реальное" значение свойства Visible?
Ответ 1
Ну, регулярная реализация проверяет контрольный стек, чтобы убедиться, что все родители видны. Единственный способ, которым я знаю, это увернуться от этого - обмануть с отражением и просить 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 });
Ответ 2
Что я сделал, это временно удалить кнопку из своих родительских элементов управления, чтобы проверить ее видимое значение, а затем повторно добавить к родительским элементам управления.
Если вам нужно, вы можете отслеживать дочерний индекс, чтобы повторно добавить его в нужный индекс.
Ответ 3
Опция, которая не полагается на рефлексию, должна состоять в том, чтобы возвратить родителям иерархии управления, ища одно значение с видимым значением в false.
EDIT: См. комментарии для значимости кода.
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);
Ответ 4
У меня такая же проблема с классами, полученными из базового класса ToolStripItem. поэтому я использовал значение Available property, чтобы проверить, будет ли элемент отображаться или нет. задача решена. Пример:
ToolStripItem curItm = menuStrip1.Items[i] as ToolStripItem;
if(curItm is ToolStripItem && curItm.Available) DoAnyThing();
В этом примере "curItm" является экземпляром производного класса ToolStripItem.
Эта проблема с свойствами Visible/Enabled в элементах .Net, которые зависят от родительского контейнера Visible/Enabled, должна быть решена командой .Net. Я создаю свойство costume с именем IsVisible/IsEnabled в моих собственных классах, которые возвращают назначенное значение для свойств Visible/Enabled, а не значение, зависящее от родительского контейнера.