天天看點

WPF之路——使用者控件對比自定義控件UserControl VS CustomControl)

  • 将多個現有的控件組合成一個可重用的“組”。
  • 由一個XAML檔案和一個背景代碼檔案。
  • 不能使用樣式和模闆。
  • 繼承自UserControl類。

自定義控件(擴充)

  • 在現有的控件上進行擴充,增加一些新的屬性方法等。
  • 包括一個代碼檔案和一個預設的主題檔案。
  • 可以使用樣式和模闆。
  • 建構控件庫的好方法。

=======================================================================

UserControl主要是現有控件的組合。組合是好組合啊,我随便拖幾個控件往頁面裡面一放,比如我弄個TextBox和一個button往頁面裡面一方,起個名字就是UserControl了,問題是這個UserControl光能看不能用啊。比如說我在WPF窗體裡面要對這個UserControl裡面的TextBox指派或者擷取它的值,咋擷取?我想點選UserControl裡的Button來觸發這個UserControl所在的WPF窗體背景代碼檔案裡面(暫不提MVVM模式)的某個事件,怎麼觸發?這兩個問題才是建立UserControl的關鍵問題。

第一個問題:擷取或設定屬性。

建立一個wpf使用者控件項目,在UserControl1.xaml裡添加一個Button和TextBox。使用者控件預設繼承自UserControl類,你也可以修改他的所繼承的類。若修改為其他類,UserControl則将擁有這個類的相應的方法和屬性。這裡先不修改,保持其預設的繼承。

現在的主要任務是當這個使用者控件放到WPF窗體裡面後,在窗體裡能擷取或設定裡面的 TextBox的值。

關鍵的一步是為這個使用者控件添加一個依賴屬性。

比如我要給這個使用者控件添加一個Text屬性,即當我将這個使用者控件放到WPF視窗裡要擷取或者設定它的Text屬性。

添加這個Text依賴屬性的代碼如下:

這樣就為這個使用者控件

public static readonly DependencyProperty TextProperty =
           DependencyProperty.Register("Text", typeof(string),
           typeof(UserControl1),
           new PropertyMetadata("TextBox", new PropertyChangedCallback(OnTextChanged)));
        public string Text
        {
            get { return (string)GetValue(TextProperty); }

            set { SetValue(TextProperty, value); }
        }

        static void OnTextChanged(object sender, DependencyPropertyChangedEventArgs args)
        {
            UserControl1 source = (UserControl1)sender;
            source.tb.Text = (string)args.NewValue;
        }      

增加了一個名字為Text的屬性。若你剛好正在做這方面或者學習這方面的東西,你通過搜尋看到了這篇文章估計有人會直接把上面的代碼一下看實作了,心裡很高興。這樣是很快,但是這是哪走了魚而不是漁。這裡面主要的句代碼是

public static readonly DependencyProperty TextProperty =
           DependencyProperty.Register("Text", typeof(string),
           typeof(UserControl1),
           new PropertyMetadata("TextBox", new PropertyChangedCallback(OnTextChanged)));      

然後主要是DependencyProperty.Register方法。

第一個參數,是你要為這個使用者控件增加的屬性的名字,即你在第一個參數裡面填寫什麼字元串将來你的使用者控件将會增加以這個字元串為名字的屬性。

第二個參數是指這個屬性對應的資料類型。

第三個參數這個屬性所有者的類型。

第四個參數屬性改變時觸發的回調事件。

這個方法及其參數弄懂後,就很容易來為使用者控件增加屬性了。

下面第二個大問題,事件傳閱。

public static readonly RoutedEvent MyButtonClickEvent =
            EventManager.RegisterRoutedEvent("MyButtonClick", RoutingStrategy.Bubble, typeof(RoutedPropertyChangedEventHandler<object>), typeof(UserControl1));

        public event RoutedPropertyChangedEventHandler<object> MyButtonClick
        {
            add
            {
                this.AddHandler(MyButtonClickEvent, value);
            }

            remove
            {
                this.RemoveHandler(MyButtonClickEvent, value);
            }
        }

        public void OnMyButtonClick(object oldValue, object newValue)
        {
            RoutedPropertyChangedEventArgs<object> arg =
                new RoutedPropertyChangedEventArgs<object>(oldValue, newValue, MyButtonClickEvent);
           
            this.RaiseEvent(arg);
        }      
public class MyButtonSimple: Button
{
    // Create a custom routed event by first registering a RoutedEventID
    // This event uses the bubbling routing strategy
    public static readonly RoutedEvent TapEvent = EventManager.RegisterRoutedEvent(
        "Tap", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(MyButtonSimple));

    // Provide CLR accessors for the event
    public event RoutedEventHandler Tap
    {
            add { AddHandler(TapEvent, value); } 
            remove { RemoveHandler(TapEvent, value); }
    }

    // This method raises the Tap event
    void RaiseTapEvent()
    {
            RoutedEventArgs newEventArgs = new RoutedEventArgs(MyButtonSimple.TapEvent);
            RaiseEvent(newEventArgs);
    }
    // For demonstration purposes we raise the event when the MyButtonSimple is clicked
    protected override void OnClick()
    {
        RaiseTapEvent();
    }

}