Udostępnij za pośrednictwem


Omówienie dołączonych właściwości (WPF .NET)

Dołączona właściwość to koncepcja języka XAML (Extensible Application Markup Language). Dołączone właściwości umożliwiają ustawienie dodatkowych par właściwości/wartości dla dowolnego elementu XAML pochodzącego z DependencyObject, mimo że element nie definiuje tych dodatkowych właściwości w modelu obiektów. Dodatkowe właściwości są dostępne globalnie. Dołączone właściwości są zazwyczaj definiowane jako specjalistyczna forma właściwości zależności, która nie ma konwencjonalnego opakowania właściwości.

Warunki wstępne

Zakłada się, że masz podstawową wiedzę na temat właściwości zależności i że przeczytałeś omówienie właściwości zależności . Aby postępować zgodnie z przykładami w tym artykule, warto zapoznać się z językiem XAML i wiedzieć, jak pisać aplikacje programu Windows Presentation Foundation (WPF).

Dlaczego warto używać dołączonych właściwości

Dołączona właściwość umożliwia elementowi podrzędnemu określenie unikatowej wartości właściwości zdefiniowanej w elemencie nadrzędnym. Typowym scenariuszem jest element podrzędny określający sposób renderowania go w interfejsie użytkownika przez jego element nadrzędny. Na przykład DockPanel.Dock jest dołączoną właściwością, ponieważ jest ustawiona na elementach podrzędnych DockPanel, a nie na samym DockPanel. Klasa DockPanel definiuje pole statyczne DependencyProperty o nazwie DockProperty, a następnie udostępnia metody GetDock i SetDock jako publiczne metody dostępu dla dołączonej właściwości.

Dołączone właściwości w języku XAML

W języku XAML ustawiasz dołączone właściwości przy użyciu składni <attached property provider type>.<property name>, gdzie dołączony dostawca właściwości jest klasą definiującą dołączoną właściwość. W poniższym przykładzie pokazano, jak element podrzędny DockPanel może ustawić wartość właściwości DockPanel.Dock.

<DockPanel>
    <TextBox DockPanel.Dock="Top">Enter text</TextBox>
</DockPanel>

Użycie jest podobne do właściwości statycznej, gdzie odwołujesz się do typu, który jest właścicielem i rejestruje właściwość dołączoną (na przykład DockPanel), a nie nazwę wystąpienia.

Po określeniu dołączonej właściwości za pomocą atrybutu XAML, możliwe jest tylko jej ustawienie. Nie można bezpośrednio uzyskać wartości właściwości za pomocą języka XAML, chociaż istnieją pewne mechanizmy pośrednie do porównywania wartości, takich jak wyzwalacze w stylach.

Dołączone właściwości w WPF

Dołączone właściwości są koncepcją XAML, właściwości zależności są koncepcją WPF. W WPF większość dołączonych właściwości związanych z interfejsem użytkownika w typach WPF jest implementowana jako właściwości zależne. Właściwości dołączone WPF, które są implementowane jako właściwości zależności, wspierają koncepcje właściwości zależności, takie jak metadane, w tym domyślne wartości z metadanych.

Dołączone modele użycia właściwości

Mimo że dowolny obiekt może ustawić dołączoną wartość właściwości, nie oznacza to ustawienia wartości spowoduje wygenerowanie namacalnego wyniku lub wartość będzie używana przez inny obiekt. Głównym celem właściwości dołączanych jest zapewnienie sposobu, w jaki obiekty z różnych hierarchii klas i relacji logicznych mogą przekazywać wspólne informacje do typu definiującego właściwość dołączaną. Użycie dołączonych właściwości zwykle jest zgodne z jednym z następujących modeli:

  • Typ definiujący dołączoną właściwość jest elementem nadrzędnym elementów, które ustawiają wartości dla dołączonej właściwości. Typ nadrzędny iteruje swoje obiekty podrzędne za pomocą wewnętrznej logiki, która operuje na strukturze drzewa obiektów, pozyskuje wartości i w pewien sposób na nich działa.
  • Typ definiujący dołączoną właściwość jest używany jako element podrzędny dla różnych możliwych elementów nadrzędnych i modeli zawartości.
  • Typ definiujący dołączoną właściwość reprezentuje usługę. Inne typy ustawiają wartości dla dołączonej właściwości. Następnie, gdy element, który ustawił właściwość jest oceniany w kontekście usługi, przypisane wartości właściwości są uzyskiwane za pomocą wewnętrznej logiki klasy usługi.

Przykład właściwości dołączonej, zdefiniowanej przez rodzica

Typowy scenariusz, w którym WPF definiuje dołączoną właściwość, jest wtedy, gdy element nadrzędny obsługuje kolekcję elementów podrzędnych, a element nadrzędny implementuje zachowanie na podstawie danych zgłaszanych przez poszczególne elementy podrzędne.

DockPanel definiuje właściwość przypisaną DockPanel.Dock. DockPanel ma kod na poziomie klasy, w szczególności MeasureOverride i ArrangeOverride, który jest częścią logiki renderowania. Wystąpienie DockPanel sprawdza, czy którykolwiek z jego bezpośrednich elementów podrzędnych ustawił wartość dla DockPanel.Dock. Jeśli tak, te wartości stają się danymi wejściowymi logiki renderowania zastosowanej do każdego elementu podrzędnego. Chociaż teoretycznie możliwe jest, aby dołączone właściwości miały wpływ na elementy poza bezpośrednim elementem nadrzędnym, zdefiniowane zachowanie dla zagnieżdżonego wystąpienia DockPanel polega tylko na interakcji z jego bezpośrednim kolekcją elementów podrzędnych. Dlatego jeśli ustawisz DockPanel.Dock dla elementu, który nie ma nadrzędnego DockPanel, nie zostanie zgłoszony błąd lub wyjątek i zostanie utworzona wartość właściwości globalnej, która nie zostanie wykorzystana przez żadne DockPanel.

Dołączone właściwości w kodzie

Dołączane właściwości w WPF nie mają typowych metod opakowujących CLR (get i set), ponieważ mogą być ustawiane spoza przestrzeni nazw CLR. Aby umożliwić procesorowi XAML ustawienie tych wartości podczas analizowania kodu XAML, klasa definiująca dołączoną właściwość musi implementować dedykowane metody dostępu w postaci Get<property name> i Set<property name>.

Możesz również użyć dedykowanych metod dostępu, aby uzyskać i ustawić dołączoną właściwość w kodzie, jak pokazano w poniższym przykładzie. W tym przykładzie myTextBox jest wystąpieniem klasy TextBox.

DockPanel myDockPanel = new();
TextBox myTextBox = new();
myTextBox.Text = "Enter text";

// Add child element to the DockPanel.
myDockPanel.Children.Add(myTextBox);

// Set the attached property value.
DockPanel.SetDock(myTextBox, Dock.Top);
Dim myDockPanel As DockPanel = New DockPanel()
Dim myTextBox As TextBox = New TextBox()
myTextBox.Text = "Enter text"

' Add child element to the DockPanel.
myDockPanel.Children.Add(myTextBox)

' Set the attached property value.
DockPanel.SetDock(myTextBox, Dock.Top)

Jeśli nie dodasz myTextBox jako elementu podrzędnego myDockPanel, wywołanie SetDock nie zgłosi wyjątku ani nie będzie miało żadnego wpływu. Tylko wartość DockPanel.Dock ustawiona na element podrzędny DockPanel może mieć wpływ na renderowanie, przy czym renderowanie pozostanie takie samo niezależnie od tego, czy ustawisz wartość przed dodaniem elementu podrzędnego do DockPanel, czy po.

Z perspektywy kodu właściwość dołączona jest jak pole pomocnicze, które ma akcesory metod zamiast akcesorów właściwości i które można ustawić na dowolnym obiekcie bez potrzeby wcześniejszego definiowania w tych obiektach.

Metadane dołączonej właściwości

Metadane dołączonej właściwości zwykle nie różnią się od właściwości zależności. Podczas rejestrowania dołączonej właściwości należy użyć FrameworkPropertyMetadata, aby określić właściwości właściwości, takie jak wpływ właściwości na renderowanie lub pomiar. Po określeniu wartości domyślnej poprzez zastąpienie metadanych dołączonej właściwości, ta wartość staje się domyślna dla niejawnej dołączonej właściwości w instancjach klasy, która ją nadpisuje. Jeśli wartość dołączonej właściwości nie jest ustawiona w inny sposób, wartość domyślna jest zgłaszana, gdy właściwość jest odpytywana za pomocą akcesora Get<property name> z wystąpieniem klasy, w którym określono metadane.

Aby włączyć dziedziczenie wartości właściwości we właściwości, użyj dołączonych właściwości zamiast właściwości zależności, które nie są dołączone. Aby uzyskać więcej informacji, zobacz dziedziczenie wartości właściwości.

Niestandardowe dołączone właściwości

Kiedy utworzyć dołączoną właściwość

Tworzenie dołączonej właściwości jest przydatne, gdy:

  • Potrzebny jest mechanizm ustawiania właściwości dostępny dla klas innych niż klasa definiująca. Typowym scenariuszem jest układ interfejsu użytkownika, na przykład DockPanel.Dock, Panel.ZIndexi Canvas.Top są przykładami istniejących właściwości układu. W scenariuszu układu elementy podrzędne elementu układu sterującego są w stanie wyrazić wymagania względem swojego elementu nadrzędnego i ustawić wartość dla właściwości dołączonej zdefiniowanej przez element nadrzędny.

  • Jedna z twoich klas reprezentuje usługę i chcesz, aby inne klasy integrowały tę usługę w bardziej przejrzysty sposób.

  • Potrzebujesz obsługi projektanta WPF programu Visual Studio, w tym możliwość edycji właściwości za pośrednictwem okna Właściwości. Aby uzyskać więcej informacji, zobacz omówienie tworzenia i zarządzania kontrolkami Control.

  • Chcesz użyć dziedziczenia wartości właściwości.

Jak utworzyć dołączoną właściwość

Jeśli klasa definiuje dołączoną właściwość wyłącznie do użytku przez inne typy, klasa nie musi pochodzić z DependencyObject. W przeciwnym razie postępuj zgodnie z modelem WPF, aby dołączona właściwość była również właściwością zależności, wyprowadzając swoją klasę z DependencyObject.

Zdefiniuj dołączoną właściwość jako zależność w klasie definiującej, deklarując pole public static readonly typu DependencyProperty. Następnie przypisz wartość zwracaną metody RegisterAttached do pola, czyli identyfikatora właściwości zależności :. Postępuj zgodnie z konwencją nazewnictwa właściwości WPF, która odróżnia pola od właściwości, które reprezentują, nazewając pole identyfikatora <property name>Property. Ponadto zapewnij metody dostępu statycznego Get<property name> i Set<property name>, które umożliwiają systemowi właściwości uzyskanie dostępu do przypisanej właściwości.

W poniższym przykładzie pokazano, jak zarejestrować właściwość zależności przy użyciu metody RegisterAttached oraz jak zdefiniować metody dostępu. W tym przykładzie nazwa dołączonej właściwości to HasFish, więc pole identyfikatora nosi nazwę HasFishProperty, a metody akcesorów mają nazwę GetHasFish i SetHasFish.

public class Aquarium : UIElement
{
    // Register an attached dependency property with the specified
    // property name, property type, owner type, and property metadata.
    public static readonly DependencyProperty HasFishProperty = 
        DependencyProperty.RegisterAttached(
      "HasFish",
      typeof(bool),
      typeof(Aquarium),
      new FrameworkPropertyMetadata(defaultValue: false,
          flags: FrameworkPropertyMetadataOptions.AffectsRender)
    );

    // Declare a get accessor method.
    public static bool GetHasFish(UIElement target) =>
        (bool)target.GetValue(HasFishProperty);

    // Declare a set accessor method.
    public static void SetHasFish(UIElement target, bool value) =>
        target.SetValue(HasFishProperty, value);
}
Public Class Aquarium
    Inherits UIElement

    ' Register an attached dependency property with the specified
    ' property name, property type, owner type, and property metadata.
    Public Shared ReadOnly HasFishProperty As DependencyProperty =
        DependencyProperty.RegisterAttached("HasFish", GetType(Boolean), GetType(Aquarium),
            New FrameworkPropertyMetadata(defaultValue:=False,
                flags:=FrameworkPropertyMetadataOptions.AffectsRender))

    ' Declare a get accessor method.
    Public Shared Function GetHasFish(target As UIElement) As Boolean
        Return target.GetValue(HasFishProperty)
    End Function

    ' Declare a set accessor method.
    Public Shared Sub SetHasFish(target As UIElement, value As Boolean)
        target.SetValue(HasFishProperty, value)
    End Sub

End Class

Akcesor Get

Sygnatura metody dostępu get to public static object Get<property name>(DependencyObject target), gdzie:

  • target to DependencyObject, z której odczytywana jest dołączona właściwość. Typ target może być bardziej szczegółowy niż DependencyObject. Na przykład metoda dostępu DockPanel.GetDock wpisze target jako UIElement, ponieważ dołączona właściwość ma być ustawiona na wystąpieniach UIElement. UiElement pośrednio pochodzi z DependencyObject.
  • Typ zwracany może być bardziej szczegółowy niż object. Na przykład metoda GetDock wpisze zwróconą wartość jako Dock, ponieważ zwracana wartość powinna być wyliczeniem Dock.

Notatka

Akcesorium get dla dołączonej właściwości jest wymagane do obsługi powiązań danych w narzędziach projektowych, takich jak Visual Studio lub Blend for Visual Studio.

Akcesor ustawiający

Sygnatura metody dostępowej set to public static void Set<property name>(DependencyObject target, object value), gdzie:

  • target jest DependencyObject, na którym jest zapisywana dołączona właściwość. Typ target może być bardziej szczegółowy niż DependencyObject. Na przykład metoda SetDock typuje target jako UIElement, ponieważ dołączona właściwość ma zostać ustawiona na wystąpienia UIElement. UiElement pośrednio pochodzi z DependencyObject.
  • Typ value może być bardziej szczegółowy niż object. Na przykład metoda SetDock wymaga wartości Dock. Moduł ładujący XAML musi mieć możliwość wygenerowania typu value z ciągu znaczników reprezentującego wartość dołączonej właściwości. W związku z tym, dla używanego typu musi istnieć wsparcie w postaci konwersji typów, serializatora wartości lub rozszerzenia znaczników.

Dołączone atrybuty właściwości

WPF definiuje kilka atrybutów platformy .NET, które udostępniają informacje o dołączonych właściwościach do procesów odbicia, a także dla konsumentów informacji o odbiciem i właściwościach, takich jak projektanci. Projektanci używają zdefiniowanych atrybutów platformy .NET WPF, aby ograniczyć właściwości wyświetlane w oknie właściwości, aby uniknąć przeciążenia użytkowników z globalną listą wszystkich dołączonych właściwości. Możesz rozważyć zastosowanie tych atrybutów do swoich niestandardowych właściwości dołączonych. Przeznaczenie i składnia atrybutów platformy .NET są opisane na tych stronach referencyjnych:

Dowiedz się więcej

  • Aby uzyskać więcej informacji na temat tworzenia dołączonej właściwości, zobacz Rejestrowanie dołączonej właściwości.
  • Aby uzyskać bardziej zaawansowane scenariusze użycia właściwości zależności i dołączonych właściwości, zobacz Niestandardowe właściwości zależności.
  • Właściwość można zarejestrować zarówno jako dołączoną właściwość, jak i właściwość zależności, i dołączyć konwencjonalne otoki właściwości. W ten sposób właściwość można ustawić na elemencie przy użyciu opakowań właściwości, a także dla dowolnego innego elementu przy użyciu składni dołączonych właściwości XAML. Aby zapoznać się z przykładem, zobacz FrameworkElement.FlowDirection.

Zobacz też