编写自定义控件时,总是继承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 On
{
if (TextChanged != null)
TextChanged(this, new EventArgs());
}
事实上不需要重写On
我写自定义控件时就碰到这个问题,网上搜索一遍,照例无结果(为啥要说照例……),只得自己花点时间弄一下,记下来免得以后又忘了。
比较有趣的是,在搜索的过程中,去了MSDN的中英文论坛,有人提过这个问题,而版主的回答无一例外是不能实现,只能用BrowsableAttribute在属性浏览器中隐藏……其实我一度也想放弃,因为从面向对象的角度来看,这些版主的回答并没错误,要不是突然想到PictureBox控件,还真以为实现不了了……事实上我没什么耐心,要是早把System.ComponentModel下所有的Attribute类全部仔细看一遍(开始是看过,不过是一目十行这么看下来的……)也就不需要去网上搜索一圈无结果,再回来老老实实看文档了。