Szukaj…


Wprowadzenie

Właściwości zależności są rodzajem właściwości, które rozszerzają właściwość CLR. Podczas gdy właściwość CLR jest odczytywana bezpośrednio od członka klasy, właściwość zależności będzie dynamicznie rozstrzygana podczas wywoływania metody GetValue (), którą Twój obiekt uzyskuje dzięki dziedziczeniu z podstawowej klasy DependencyObject.

Ta sekcja podzieli właściwości zależności i wyjaśni ich użycie zarówno koncepcyjnie, jak i na przykładach kodu.

Składnia

  • DependencyProperty.Register (nazwa ciągu, TypeTypeType, TypeTypeType)
  • DependencyProperty.Register (nazwa ciągu, TypeTypeType, Type ownerType, PropertyMetadata typeMetadata)
  • DependencyProperty.Register (nazwa ciągu, typ typeType, typ ownerType, PropertyMetadata typeMetadata, ValidateValueCallback validateValueCallback)
  • DependencyProperty.RegisterAttached (nazwa ciągu, TypeTypeType, TypeTypeType)
  • DependencyProperty.RegisterAttached (nazwa ciągu, typ propertyType, typ ownerType, PropertyMetadata typeMetadata)
  • DependencyProperty.RegisterAttached (nazwa ciągu, typ propertyType, typ ownerType, PropertyMetadata typeMetadata, ValidateValueCallback validateValueCallback)
  • DependencyProperty.RegisterReadOnly (nazwa ciągu, typ propertyType, typ ownerType, PropertyMetadata typeMetadata)
  • DependencyProperty.RegisterReadOnly (nazwa ciągu, typ propertyType, typ ownerType, PropertyMetadata typeMetadata, ValidateValueCallback validateValueCallback)
  • DependencyProperty.RegisterAttachedReadOnly (nazwa ciągu, typ propertyType, typ ownerType, PropertyMetadata typeMetadata)
  • DependencyProperty.RegisterAttachedReadOnly (nazwa ciągu, typ propertyType, typ ownerType, PropertyMetadata typeMetadata, ValidateValueCallback validateValueCallback)

Parametry

Parametr Detale
Nazwa String reprezentujący nazwę właściwości
Typ nieruchomości Type właściwości, np. typeof(int)
ownerType Type klasy, w której definiowana jest właściwość, np. typeof(MyControl) lub typeof(MyAttachedProperties) .
typeMetadata Wystąpienie System.Windows.PropertyMetadata (lub jednej z jego podklas), które definiuje wartości domyślne, wywołania zwrotne zmienione właściwości, FrameworkPropertyMetadata pozwala zdefiniować opcje wiązania, takie jak System.Windows.Data.BindingMode.TwoWay .
validateValueCallback Niestandardowe wywołanie zwrotne, które zwraca true, jeśli nowa wartość właściwości jest poprawna, w przeciwnym razie false.

Standardowe właściwości zależności

Kiedy użyć

Praktycznie wszystkie kontrolki WPF intensywnie wykorzystują właściwości zależności. Właściwość zależności pozwala na korzystanie z wielu funkcji WPF, które nie są możliwe w przypadku samych standardowych właściwości CLR, w tym między innymi obsługę stylów, animacji, powiązania danych, dziedziczenia wartości i powiadomień o zmianach.

Właściwość TextBox.Text jest prostym przykładem tego, gdzie potrzebna jest standardowa właściwość zależności. W tym przypadku powiązanie danych nie byłoby możliwe, gdyby Text był standardową właściwością CLR.

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

Jak zdefiniować

Właściwości zależności można zdefiniować tylko w klasach pochodzących z DependencyObject , takich jak FrameworkElement , Control itp.

Jednym z najszybszych sposobów utworzenia standardowej właściwości zależności bez konieczności pamiętania składni jest użycie fragmentu „propdp”, wpisując propdp a następnie naciskając klawisz Tab . Zostanie wstawiony fragment kodu, który można następnie zmodyfikować zgodnie z własnymi potrzebami:

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));
}

Powinieneś tabulować różne części fragmentu kodu, aby wprowadzić niezbędne zmiany, w tym zaktualizować nazwę właściwości, typ właściwości, typ klasy i wartość domyślną.

Ważne konwencje

Istnieje kilka ważnych konwencji / zasad, których należy przestrzegać:

  1. Utwórz właściwość CLR dla właściwości zależności. Ta właściwość jest używana w kodzie obiektu lub przez innych konsumentów. Powinien wywoływać GetValue i SetValue aby konsumenci nie musieli.

  2. Nazwij właściwość zależności poprawnie. Pole DependencyProperty powinno być public static readonly . Powinien mieć nazwę, która odpowiada nazwie właściwości CLR i kończy się na „Właściwość”, np. Text i TextProperty .

  3. Nie dodawaj dodatkowej logiki do ustawiacza właściwości CLR. System właściwości zależności (a konkretnie XAML) nie korzysta z właściwości CLR. Jeśli chcesz wykonać akcję, gdy zmieni się wartość właściwości, musisz podać wywołanie zwrotne za pośrednictwem 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.
    }
    

Tryb wiązania

Aby wyeliminować potrzebę określania Mode=TwoWay w powiązaniach (podobnie jak zachowanie TextBox.Text ), zaktualizuj kod, aby używał FrameworkPropertyMetadata zamiast PropertyMetadata i określ odpowiednią flagę:

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

Dołączone właściwości zależności

Kiedy użyć

Załączona właściwość jest właściwością zależności, którą można zastosować do dowolnego obiektu DependencyObject celu poprawy zachowania różnych elementów sterujących lub usług, które są świadome istnienia tej właściwości.

Niektóre przypadki użycia dołączonych właściwości obejmują:

  1. Posiadanie elementu rodzica iteruje przez swoje dzieci i działa na nie w określony sposób. Na przykład formant Grid korzysta z Grid.Row , Grid.Column , Grid.RowSpan i Grid.ColumnSpan , aby uporządkować elementy w wierszach i kolumnach.
  2. Dodawanie elementów wizualnych do istniejących kontrolek za pomocą niestandardowych szablonów, np. Dodawanie znaków wodnych do pustych pól tekstowych w całej aplikacji bez konieczności podklasy TextBox .
  3. Zapewnienie ogólnej usługi lub funkcji dla niektórych lub wszystkich istniejących formantów, np. ToolTipService lub FocusManager . Są to powszechnie określane jako zachowania przywiązane .
  4. Podczas dziedziczenia w dół wymagane jest drzewo wizualne, np. Podobnie jak zachowanie DataContext .

To dodatkowo pokazuje, co dzieje się w przypadku użycia Grid :

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>

    <Label Grid.Column="0" Content="Your Name:" />
    <TextBox Grid.Column="1" Text="{Binding FirstName}" />
</Grid>

Grid.Column nie jest właściwością istniejącą w Label lub TextBox . Kontrolka Grid raczej przegląda elementy potomne i układa je zgodnie z wartościami dołączonych właściwości.

Jak zdefiniować

W tym przykładzie będziemy nadal używać Grid . Definicja Grid.Column jest pokazana poniżej, ale DependencyPropertyChangedEventHandler jest wykluczony ze względu na zwięzłość.

public static readonly DependencyProperty RowProperty =
    DependencyProperty.RegisterAttached("Row", typeof(int), typeof(Grid),
        new FrameworkPropertyMetadata(0, ...));

public static void SetRow(UIElement element, int value)
{
    if (element == null)
        throw new ArgumentNullException("element");

    element.SetValue(RowProperty, value);
}

public static int GetRow(UIElement element)
{
    if (element == null)
        throw new ArgumentNullException("element");

    return ((int)element.GetValue(RowProperty));
}

Ponieważ dołączone właściwości mogą być dołączone do wielu różnych elementów, nie można ich zaimplementować jako właściwości CLR. Zamiast tego wprowadzono parę metod statycznych.

Dlatego, w przeciwieństwie do standardowych właściwości zależności, właściwości dołączone można również zdefiniować w klasach, które nie pochodzą z DependencyObject .

Obowiązują tu również te same konwencje nazewnictwa, które mają zastosowanie do zwykłych właściwości zależności: właściwość zależności RowProperty ma odpowiednie metody GetRow i SetRow .

Ostrzeżenia

Jak udokumentowano na MSDN :

Chociaż może wydawać się, że dziedziczenie wartości właściwości działa w przypadku niepowiązanych właściwości zależności, zachowanie dziedziczenia w przypadku nieprzyłączonej właściwości przez pewne granice elementów w drzewie wykonawczym jest niezdefiniowane. Zawsze używaj RegisterAttached do rejestrowania właściwości, w których określasz Dziedziczenia w metadanych.

Właściwości zależności tylko do odczytu

Kiedy użyć

Właściwość zależności tylko do odczytu jest podobna do normalnej właściwości zależności, ale jest tak skonstruowana, aby nie zezwalać na ustawianie jej wartości poza kontrolą. Działa to dobrze, jeśli mają właściwość, która ma charakter wyłącznie informacyjny dla konsumentów, np IsMouseOver lub IsKeyboardFocusWithin .

Jak zdefiniować

Podobnie jak standardowe właściwości zależności, właściwość zależności tylko do odczytu musi zostać zdefiniowana w klasie wywodzącej się z DependencyObject .

public class MyControl : Control
{
    private static readonly DependencyPropertyKey MyPropertyPropertyKey = 
        DependencyProperty.RegisterReadOnly("MyProperty", typeof(int), typeof(MyControl),
            new FrameworkPropertyMetadata(0));

    public static readonly DependencyProperty MyPropertyProperty = MyPropertyPropertyKey.DependencyProperty;

    public int MyProperty
    {
        get { return (int)GetValue(MyPropertyProperty); }
        private set { SetValue(MyPropertyPropertyKey, value); }
    }
}

Obowiązują tu również te same konwencje, które dotyczą normalnych właściwości zależności, ale z dwiema kluczowymi różnicami:

  1. DependencyProperty pochodzi z private DependencyPropertyKey .
  2. Narzędzie do ustawiania właściwości CLR jest protected lub private zamiast public .

Zauważ, że ustawiający przekazuje MyPropertyPropertyKey a nie MyPropertyProperty do metody SetValue . Ponieważ właściwość została zdefiniowana jako tylko do odczytu, każda próba użycia SetValue we właściwości musi być używana z przeciążeniem, które otrzymuje DependencyPropertyKey ; w przeciwnym razie zostanie InvalidOperationException .



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow