为什么从其父触发器VisibilityChanged中移除一个控件,其Visible = true?

时间:2015-09-01 19:56:06

标签: c# winforms

我正在使用一些遗留代码,我无法进行大的更改。 有一个控件具有与OnVisibleChanged事件关联的逻辑。

在应用程序生命周期中的某个时刻,控件将从其父级中删除,当发生这种情况时,OnVisibileChanged事件将被触发两次。第一次控件的可见性为false,第二次为true

为什么会这样?为什么第二次触发可见性变化并且Visible为真?

重现我描述的行为的简单方法:

创建一个控件:

class MyButton: Button
    {
        public MyButton()
        {
            Text = "Test";
        }

        protected override void OnVisibleChanged(EventArgs e)
        {
            base.OnVisibleChanged(e);


            MessageBox.Show(string.Format("Im now visible {0}", Visible));
        }        
    }

在表单中使用它,并在otherButton的点击事件中删除它:

public partial class Form1 : Form
    {
        private MyButton myButton = new MyButton();
        private GroupBox myGroupBox = new GroupBox();
        private Button otherButton = new Button();
        public Form1()
        {
            InitializeComponent();

            otherButton.Text = "Remove";            
            otherButton.Click += otherButton_Click;
            this.myGroupBox.Controls.Add(myButton);
            this.Controls.Add(otherButton);
            this.Controls.Add(myGroupBox);

        }

        void otherButton_Click(object sender, EventArgs e)
        {
            myGroupBox.Controls.Remove(myButton);
        }        
    }

运行此功能后,如果您点击otherButton,则会显示两次消息,首先是可见性为false,第二次为true

1 个答案:

答案 0 :(得分:0)

The cause is rooted somewhere in the native call to:

[DllImport("user32.dll")]
public static extern IntPtr SetParent(HandleRef hWnd, HandleRef hWndParent);

which is called in the Control.Remove(...) method. If you replace Controls.Remove(myButton); with SetParent(myButton.Handle, IntPtr.Zero); the same two events will fire.

My guess is that it is convenient to have the VisibleChanged event fire when the control is removed from its parent. However, the control was never explicitly hidden though. So the second call has to set the Visible property back to true. Otherwise if the button is added back to the control, it won't be visible.