C#中自定义控件隐藏基类成员(属性、方法和事件)的方法

时间:2022-08-31 08:15:23

       编写自定义控件时,总是继承C#中提供的Control类,而Control类是C#中所有窗体控件的基类,里面定义了大量的属性、方法和事件,而很多基类成员在自定义控件中可能不需要,因为编写者会希望在自定义控件中隐藏这些成员,避免使用者调用这些成员。

       从面向对象的角度来看,不允许调用子类者访问其基类的公共成员是不可能的,我们不可能去掉或者改写基类的公共成员,即使基类成员是抽象的或是虚的,重写时也不可能修改其可访问性。

       即然不能做到真正的“去掉”不需要的基类成员,那我们只能另想办法了。实际上C#中的PictureBox就是一个很好的例子,在代码编辑器中,你在智能感应器中是找不到PictureBox的Text属性的,但是如果你强行写一行:pictureBox1.Text="aaa";这样的代码,编译器也不会报错。显然,Text是基类Control的属性,PictureBox仍然继承了它,并且可以访问它,只是使用者无法通过智能感应器访问,在设计时的属性窗口中也找不到它而已,事实上实现这一点就够了。

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public override string Text
        {
            get { return base.Text; }
            set { base.Text = value; }
        }

      以上这段代码就是实现这个目的。重写基类Text属性,BrowsableAttribute定义该属性不在属性浏览器中显示,EditorBrowsableAttribute则定义该属性不在智能感应器中出现。

      对于不能重写的基类成员,也可以用new的方式隐藏基类成员。下面代码隐藏了TextChanged事件

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler TextChanged;
        protected override void OnTextChanged(EventArgs e)
        {
            if (TextChanged != null)
                TextChanged(this, new EventArgs());
        }

       事实上不需要重写OnTextChanged方法,不过由于我们重新定义的TextChanged事件从未被调用,编译器会给出一个警告,而且万一哪个调用者强行使用此事件,程序将会报错,所以还是写上的好。

       我写自定义控件时就碰到这个问题,网上搜索一遍,照例无结果(为啥要说照例……),只得自己花点时间弄一下,记下来免得以后又忘了。

       比较有趣的是,在搜索的过程中,去了MSDN的中英文论坛,有人提过这个问题,而版主的回答无一例外是不能实现,只能用BrowsableAttribute在属性浏览器中隐藏……其实我一度也想放弃,因为从面向对象的角度来看,这些版主的回答并没错误,要不是突然想到PictureBox控件,还真以为实现不了了……事实上我没什么耐心,要是早把System.ComponentModel下所有的Attribute类全部仔细看一遍(开始是看过,不过是一目十行这么看下来的……)也就不需要去网上搜索一圈无结果,再回来老老实实看文档了。