1. 程式人生 > >C#中自定義控制元件隱藏基類成員(屬性、方法和事件)的方法

C#中自定義控制元件隱藏基類成員(屬性、方法和事件)的方法

       編寫自定義控制元件時,總是繼承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類全部仔細看一遍(開始是看過,不過是一目十行這麼看下來的……)也就不需要去網上搜索一圈無結果,再回來老老實實看文件了。