標準依賴屬性

什麼時候用

實際上,所有 WPF 控制元件都會大量使用依賴項屬性。依賴項屬性允許使用許多僅使用標準 CLR 屬性不可能的 WPF 功能,包括但不限於支援樣式,動畫,資料繫結,值繼承和更改通知。

TextBox.Text 屬性是需要標準依賴項屬性的簡單示例。如果 Text 是標準 CLR 屬性,則無法進行資料繫結。

<TextBox Text="{Binding FirstName}" />

如何定義

依賴屬性只能在從 DependencyObject 派生的類中定義,例如 FrameworkElementControl 等。

在不必記住語法的情況下建立標準依賴項屬性的最快方法之一是通過鍵入 propdp 然後按下來使用 propdp 程式碼段 Tab。將插入一個程式碼片段,然後可以對其進行修改以滿足你的需求:

public class MyControl : Control
{
    public int MyProperty
    {
        get { return (int)GetValue(MyPropertyProperty); }
        set { SetValue(MyPropertyProperty, value); }
    }

    // Using a DependencyProperty as the backing store for MyProperty.
    // This enables animation, styling, binding, etc...
    public static readonly DependencyProperty MyPropertyProperty =
        DependencyProperty.Register("MyProperty", typeof(int), typeof(MyControl),
            new PropertyMetadata(0));
}

你應該 Tab 通過程式碼段的不同部分進行必要的更改,包括更新屬性名稱,屬性型別,包含類型別和預設值。

重要的慣例

這裡有一些重要的約定/規則:

  1. 為依賴項屬性建立 CLR 屬性。此屬性用於物件的程式碼隱藏或其他使用者。它應該呼叫 GetValueSetValue,以便消費者不必這樣做。

  2. 正確命名依賴項屬性。 DependencyProperty 欄位應該是 public static readonly。它應該具有與 CLR 屬性名稱對應的名稱,並以 Property 結尾,例如 TextTextProperty

  3. 不要向 CLR 屬性的 setter 新增其他邏輯。依賴項屬性系統(特別是 XAML)不使用 CLR 屬性。如果要在屬性值更改時執行操作,則必須通過 PropertyMetadata 提供回撥:

    public static readonly DependencyProperty MyPropertyProperty =
        DependencyProperty.Register("MyProperty", typeof(int), typeof(MyControl),
            new PropertyMetadata(0, MyPropertyChangedHandler));
        
    private static void MyPropertyChangedHandler(DependencyObject sender, DependencyPropertyChangedEventArgs args)
    {
        // Use args.OldValue and args.NewValue here as needed.
        // sender is the object whose property changed.
        // Some unboxing required.
    }
    

繫結模式

為了消除在繫結中指定 Mode=TwoWay 的需要(類似於 TextBox.Text 的行為),更新程式碼以使用 FrameworkPropertyMetadata 而不是 PropertyMetadata 並指定適當的標誌:

public static readonly DependencyProperty MyPropertyProperty =
    DependencyProperty.Register("MyProperty", typeof(int), typeof(MyControl), 
        new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));