【譯】為什麼命名「它」為依賴屬性(DependencyProperty)

2023-10-13 06:00:56

當我們建立新的類和成員時,我們花費了大量的時間和精力是它們儘可能的好用,好理解,好發現。通常我們會遵循.Net框架設計指南,尤其是會不斷地研究這個新類與其他類,未來計劃等內容之間的關係。

當命名依賴屬性(DependencyProperty)和依賴物件(DependencyObject)的時候也是遵循這個原則,僅僅討論如何命名,我們就大概花了幾個小時。依賴屬性(DPs)最終歸結為屬性計算和依賴的跟蹤。屬性計算並不是很特別,很多屬性都是這樣的,所以DP的本質特徵就是依賴的跟蹤,因此命名為依賴屬性。

這裡有一個例子,實際上是一段範例程式碼,顯示了幾個依賴跟蹤的例子:

<StackPanel DataContext="Hello, world" TextBlock.FontSize="22">
    <StackPanel.Resources>
        <Style TargetType="TextBlock">
            <Setter Property="FontWeight" Value="Bold" />
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Background" Value="Red" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </StackPanel.Resources>
    <TextBlock Text="{Binding}" />
</StackPanel>

程式碼範例中TextBlock的屬性有不少依賴:

  • TextBlock.Text依賴於繫結(Binding),而這裡的繫結(Binding)依賴於DataContextDataContext是從父元素StackPanel繼承下來的,因此,TextBlock.Text也依賴於樹的形狀;如果TextBlockStackPanel移除,StackPanel的值也會發生變化。
  • TextBlock.FontSize也依賴於樹。在這裡,你可以看到它從StackPanel繼承。
  • 所有的TextBlock屬性都依賴於TextBlock.style。例如,這裡是TextBlock.FontWeight來自樣式(Style)。
  • 同樣的,TextBlock.Background也依賴樣式(Style)。但在這個範例中,它在觸發器(Trigger)中設定。所以TextBlock.Background在這種情況下也取決於TextBlock.IsMouseOver

有時,如果編寫自己的依賴屬性,則需要在跟蹤依賴項上做一些輔助。當需要重新計算屬性時,可以通過呼叫InvalidateProperty來實現,通常是因為在CoerceValueCallback中參照了它。

例如,這裡有一個名為Foo的依賴屬性和一個名為FooPlus1的唯讀依賴屬性。FooPlus1只是有一個計算「Foo+1」的CoerceValueCallback。因此,Foo有一個PropertyChangedCallback,當Foo發生變化時,它會使FooPlus1失效。

public int Foo
{
    get { return (int)GetValue(FooProperty); }
    set { SetValue(FooProperty, value); }
}

// Using a DependencyProperty as the backing store for Foo.  This enables animation, styling, binding, etc...
public static readonly DependencyProperty FooProperty =
    DependencyProperty.Register("Foo", typeof(int), typeof(Window1), new PropertyMetadata(FooChangedCallback));



static void FooChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs args)
{
    // Whenever Foo changes, we need to invalidate FooPlus1, so that
    // the DependencyProperty system knows to update it (call its
    // CoerceValueCallback again).
    (d as Window1).InvalidateProperty(Window1.FooPlus1Property);
}

        
public int FooPlus1
{
    get { return (int)GetValue(FooPlus1Property); }
}

static readonly DependencyPropertyKey FooPlus1PropertyKey =
    DependencyProperty.RegisterReadOnly("FooPlus1", typeof(int), typeof(Window1), new PropertyMetadata(0, null, CoerceFooPlus1Callback));

static readonly DependencyProperty FooPlus1Property = FooPlus1PropertyKey.DependencyProperty;

static object CoerceFooPlus1Callback(DependencyObject d, object baseValue)
{
    return (d as Window1).Foo + 1;
}

原文連結:https://learn.microsoft.com/en-us/archive/blogs/mikehillberg/why-is-it-called-a-dependencyproperty