Подтвердить что ты не робот

Как получить "реальное" значение свойства Visible?

Если вы установите для свойства Visible элемента управления Windows Forms значение true, это свойство все равно возвращает false, если какое-либо из окон родительского контроля скрыто. Есть ли способ получить истинный, базовый флаг видимости элемента управления в случае скрытия родительского окна?

4b9b3361

Ответ 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, а не значение, зависящее от родительского контейнера.