Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Program Windows Presentation Foundation (WPF) udostępnia zestaw usług, których można użyć do rozszerzenia funkcjonalności właściwości typu. Zbiorczo te usługi są zwykle określane jako system właściwości WPF. Właściwość, która jest wspierana przez system właściwości WPF, jest nazywana właściwością zależności. W tym omówieniu opisano system właściwości WPF i funkcjonalność właściwości zależności. Obejmuje to sposób używania istniejących właściwości zależności w języku XAML i w kodzie. W tym omówieniu przedstawiono również wyspecjalizowane aspekty właściwości zależności, takie jak metadane właściwości zależności, oraz sposób tworzenia własnej właściwości zależności w klasie niestandardowej.
Warunki wstępne
W tym temacie założono, że masz podstawową wiedzę na temat systemu typów platformy .NET i programowania obiektowego. Aby postępować zgodnie z przykładami w tym temacie, należy również zrozumieć język XAML i wiedzieć, jak pisać aplikacje WPF. Aby uzyskać więcej informacji, zobacz Walkthrough: My first WPF desktop application.
Właściwości zależności i właściwości środowiska CLR
W WPF właściwości są zwykle eksponowane jako standardowe właściwości .NET . Na poziomie podstawowym można bezpośrednio wchodzić w interakcje z tymi właściwościami i nigdy nie wiedzieć, że są one implementowane jako właściwość zależności. Należy jednak zapoznać się z niektórymi lub wszystkimi funkcjami systemu właściwości WPF, aby móc korzystać z tych funkcji.
Celem właściwości zależności jest zapewnienie sposobu obliczenia wartości właściwości na podstawie wartości innych danych wejściowych. Te inne dane wejściowe mogą obejmować właściwości systemowe, takie jak motywy i preferencje użytkownika, mechanizmy just-in-time określania właściwości, takie jak powiązanie danych i animacje/storyboardy, szablony wielokrotnego użytku, takie jak zasoby i style, lub wartości znane poprzez relacje nadrzędne-podrzędne z innymi elementami w drzewie elementów. Ponadto można zaimplementować właściwość zależności, aby zapewnić samodzielną walidację, ustawienia domyślne, wywołania zwrotne monitorujące zmiany innych właściwości oraz system, który może wymuszać wartości właściwości na podstawie potencjalnych informacji o środowisku uruchomieniowym. Klasy pochodne mogą również zmieniać niektóre specyficzne cechy istniejącej właściwości, przesłaniając metadane właściwości zależności, zamiast przesłaniania rzeczywistej implementacji istniejących właściwości lub tworzenia nowych właściwości.
W dokumentacji zestawu SDK można określić, która właściwość jest właściwością zależności, przez obecność sekcji Informacje o właściwości zależności na zarządzanej stronie referencyjnej dla tej właściwości. Sekcja Informacje o właściwości zależności zawiera link do pola identyfikatora DependencyProperty dla tej właściwości zależności, a także zawiera listę opcji metadanych ustawionych dla tej właściwości, informacje o zastąpieniu poszczególnych klas i inne szczegóły.
Właściwości zależności z powrotem właściwości środowiska CLR
Właściwości zależności i system właściwości WPF rozszerzają funkcjonalność właściwości, zapewniając typ, który tworzy kopię zapasową właściwości, jako alternatywną implementację standardowego wzorca tworzenia kopii zapasowej właściwości z polem prywatnym. Nazwa tego typu to DependencyProperty. Innym ważnym typem definiującym system właściwości WPF jest DependencyObject. DependencyObject definiuje klasę bazową, która może rejestrować i posiadać właściwość zależności.
Poniżej wymieniono terminologię używaną z właściwościami zależności:
właściwość Dependency: właściwość, która jest wspierana przez DependencyProperty.
Identyfikator właściwości zależności: wystąpienie DependencyProperty, które jest uzyskiwane jako wartość zwracana podczas rejestrowania właściwości zależności, a następnie przechowywane jako statyczny element klasy. Ten identyfikator jest używany jako parametr dla wielu interfejsów API, które współdziałają z systemem właściwości WPF.
CLR "opakowanie": Faktyczne implementacje właściwości get i set. Te implementacje zawierają identyfikator właściwości zależności, używając go w wywołaniach GetValue i SetValue, w ten sposób zapewniając podstawę dla właściwości z użyciem systemu właściwości WPF.
Na poniższym przykładzie zdefiniowano właściwość zależności IsSpinning
i ukazano związek identyfikatora DependencyProperty z właściwością, którą określa.
public static readonly DependencyProperty IsSpinningProperty =
DependencyProperty.Register(
"IsSpinning", typeof(Boolean),
typeof(MyCode)
);
public bool IsSpinning
{
get { return (bool)GetValue(IsSpinningProperty); }
set { SetValue(IsSpinningProperty, value); }
}
Public Shared ReadOnly IsSpinningProperty As DependencyProperty =
DependencyProperty.Register("IsSpinning",
GetType(Boolean),
GetType(MyCode))
Public Property IsSpinning() As Boolean
Get
Return CBool(GetValue(IsSpinningProperty))
End Get
Set(ByVal value As Boolean)
SetValue(IsSpinningProperty, value)
End Set
End Property
Ważna jest konwencja nazewnictwa właściwości oraz jej towarzyszącego pola DependencyProperty. Nazwa pola jest zawsze nazwą właściwości z dołączonym sufiksem Property
. Aby uzyskać więcej informacji na temat tej konwencji i przyczyn tego, zobacz Właściwości zależności niestandardowych.
Ustawianie wartości właściwości
Właściwości można ustawić w kodzie lub w języku XAML.
Ustawianie wartości właściwości w języku XAML
Poniższy przykład XAML określa kolor tła przycisku jako czerwony. W tym przykładzie pokazano przypadek, w którym prosta wartość ciągu atrybutu XAML jest konwertowana przez analizator XAML WPF na typ WPF (Color, za pomocą SolidColorBrush) w wygenerowanym kodzie.
<Button Background="Red" Content="Button!"/>
Język XAML obsługuje różne formularze składni do ustawiania właściwości. Składnia używana dla określonej właściwości zależy od typu wartości używanego przez właściwość, a także innych czynników, takich jak obecność konwertera typów. Aby uzyskać więcej informacji na temat składni XAML dla ustawienia właściwości, zobacz XAML w WPF i składnia XAML w szczegółach .
Jako przykład składni innej niż atrybut, poniższy przykład XAML przedstawia inne tło przycisku. Tym razem, zamiast ustawiać jednolity kolor, tło jest ustawione na obraz wraz z elementem reprezentującym ten obraz, którego źródło jest określone jako atrybut zagnieżdżonego elementu. Jest to przykład składni elementu właściwości.
<Button Content="Button!">
<Button.Background>
<ImageBrush ImageSource="wavy.jpg"/>
</Button.Background>
</Button>
Ustawianie właściwości w kodzie
Ustawienie wartości właściwości zależności w kodzie jest zwykle tylko wywołaniem implementacji zestawu uwidocznionej przez "otokę CLR".
Button myButton = new Button();
myButton.Width = 200.0;
Dim myButton As New Button()
myButton.Width = 200.0
Uzyskanie wartości właściwości jest również zasadniczo wywołaniem implementacji funkcji "get" opakowania.
double whatWidth;
whatWidth = myButton.Width;
Dim whatWidth As Double
whatWidth = myButton.Width
Możesz również wywołać interfejsy API systemu właściwości GetValue i SetValue bezpośrednio. Nie jest to zazwyczaj konieczne, jeśli używasz istniejących właściwości (opakowania są wygodniejsze i zapewniają lepsze wyeksponowanie właściwości dla narzędzi deweloperskich), ale bezpośrednie wywoływanie interfejsów API jest właściwe w niektórych scenariuszach.
Właściwości można również ustawić w XAML, a następnie uzyskać do nich dostęp później za pośrednictwem kodu. Aby uzyskać szczegółowe informacje, zobacz ,Code-Behind i XAML w WPF.
Funkcje właściwości udostępniane przez właściwość zależności
Właściwość zależna oferuje funkcjonalność, która rozszerza działanie właściwości w przeciwieństwie do właściwości wspieranej przez pole. Często takie funkcje reprezentują lub obsługują jedną z następujących określonych funkcji:
Zasoby
Wartość właściwości zależności można ustawić, odwołując się do zasobu. Zasoby są zwykle określane jako wartość właściwości Resources
elementu głównego strony lub aplikacji (te lokalizacje umożliwiają najwygodniejszy dostęp do zasobu). W poniższym przykładzie pokazano, jak zdefiniować zasób SolidColorBrush.
<DockPanel.Resources>
<SolidColorBrush x:Key="MyBrush" Color="Gold"/>
</DockPanel.Resources>
Po zdefiniowaniu zasobu możesz odwoływać się do zasobu i użyć go do podania wartości właściwości:
<Button Background="{DynamicResource MyBrush}" Content="I am gold" />
Ten konkretny zasób jest przywołyyny jako rozszerzenia znaczników DynamicResource (w języku WPF XAML można użyć statycznego lub dynamicznego odwołania do zasobów). Aby użyć odwołania do zasobów dynamicznych, musisz ustawić właściwość zależności, ponieważ właśnie użycie dynamicznych odwołań do zasobów jest umożliwione przez system właściwości WPF. Aby uzyskać więcej informacji, zapoznaj się z zasobami XAML.
Notatka
Zasoby są traktowane jako wartość lokalna, co oznacza, że jeśli ustawisz inną wartość lokalną, usuniesz odwołanie do zasobów. Aby uzyskać więcej informacji, zobacz pierwszeństwo właściwości zależności .
Powiązanie danych
Właściwość zależności może odwoływać się do wartości za pomocą powiązania danych. Powiązanie danych działa za pomocą określonej składni rozszerzenia znaczników w języku XAML lub obiektu Binding w kodzie. W przypadku powiązania danych ostateczne ustalenie wartości właściwości jest odroczone do czasu uruchomienia, w którym wartość jest uzyskiwana ze źródła danych.
Poniższy przykład ustawia właściwość Content dla Buttonprzy użyciu powiązania zadeklarowanego w języku XAML. Powiązanie używa dziedziczonego kontekstu danych i źródła danych XmlDataProvider (nie pokazano). Powiązanie samo określa żądaną właściwość źródłową za pomocą XPath w źródle danych.
<Button Content="{Binding XPath=Team/@TeamName}"/>
Notatka
Powiązania są traktowane jako wartość lokalna, co oznacza, że jeśli ustawisz inną wartość lokalną, usuniesz powiązanie. Aby uzyskać szczegółowe informacje, zobacz hierarchia wartości właściwości zależności.
Właściwości zależności lub klasa DependencyObject nie obsługują natywnie INotifyPropertyChanged w celu powiadamiania o zmianach wartości właściwości źródłowej DependencyObject w operacjach powiązania danych. Aby uzyskać więcej informacji na temat tworzenia właściwości do użycia w powiązaniu danych, które mogą zgłaszać zmiany w obiekcie docelowym powiązania danych, zobacz Powiązanie danych — omówienie.
Style
Style i szablony to dwa główne scenariusze motywujące do używania właściwości zależności. Style są szczególnie przydatne w przypadku ustawiania właściwości definiujących interfejs użytkownika aplikacji. Style są zwykle definiowane jako zasoby w języku XAML. Style wchodzą w interakcję z systemem właściwości, ponieważ zwykle zawierają "ustawiacze" dla określonych właściwości, a także "wyzwalacze", które zmieniają wartość właściwości na podstawie bieżącej wartości innej właściwości.
Poniższy przykład tworzy prosty styl (który będzie zdefiniowany wewnątrz słownika Resources, choć nie jest on pokazany), a następnie stosuje ten styl bezpośrednio do właściwości Style w przypadku Button. Obiekt setter wewnątrz stylu ustawia właściwość Background dla stylizowanego Button na kolor zielony.
<Style x:Key="GreenButtonStyle">
<Setter Property="Control.Background" Value="Green"/>
</Style>
<Button Style="{StaticResource GreenButtonStyle}">I am green!</Button>
Aby uzyskać więcej informacji, zobacz Styleing and Templating.
Animacje
Właściwości zależności można animować. Gdy animacja jest stosowana i działa, animowana wartość ma wyższy priorytet niż każda inna wartość, jak na przykład wartość lokalna, którą właściwość ma w przeciwnym razie.
Poniższy przykład animuje Background we właściwości Button (technicznie Background jest animowana przy użyciu składni elementu właściwości w celu określenia pustej SolidColorBrush jako Background, a następnie właściwość Color tej SolidColorBrush jest właściwością bezpośrednio animowaną).
<Button>I am animated
<Button.Background>
<SolidColorBrush x:Name="AnimBrush"/>
</Button.Background>
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Loaded">
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetName="AnimBrush"
Storyboard.TargetProperty="(SolidColorBrush.Color)"
From="Red" To="Green" Duration="0:0:5"
AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
Aby uzyskać więcej informacji na temat animowania właściwości, zobacz Omówienie animacji i Omówienie storyboardów.
Przesłonięcia metadanych
Możesz zmienić niektóre zachowania właściwości zależności, przesłaniając metadane dla tej właściwości podczas dziedziczenia z klasy, która pierwotnie rejestruje właściwość zależności. Zastępowanie metadanych opiera się na identyfikatorze DependencyProperty. Zastępowanie metadanych nie wymaga ponownego implementowania właściwości. Zmiana metadanych jest obsługiwana natywnie przez system właściwości; każda klasa potencjalnie przechowuje poszczególne metadane dla wszystkich właściwości, które są dziedziczone z klas bazowych, dla poszczególnych typów.
Poniższy przykład zastępuje metadane właściwości zależności DefaultStyleKey. Zastępowanie tych metadanych właściwości zależności jest częścią wzorca implementacji, który tworzy kontrolki, które mogą używać domyślnych stylów z motywów.
public class SpinnerControl : ItemsControl
{
static SpinnerControl()
{
DefaultStyleKeyProperty.OverrideMetadata(
typeof(SpinnerControl),
new FrameworkPropertyMetadata(typeof(SpinnerControl))
);
}
}
Public Class SpinnerControl
Inherits ItemsControl
Shared Sub New()
DefaultStyleKeyProperty.OverrideMetadata(GetType(SpinnerControl), New FrameworkPropertyMetadata(GetType(SpinnerControl)))
End Sub
End Class
Aby uzyskać więcej informacji na temat zastępowania lub uzyskiwania metadanych właściwości zależnych, zobacz Metadane właściwości zależnych.
Dziedziczenie wartości właściwości
Element może dziedziczyć wartość właściwości zależnej od jego elementu nadrzędnego w drzewie obiektów.
Notatka
Zachowanie dziedziczenia wartości właściwości nie jest globalnie włączone dla wszystkich właściwości zależnych, ponieważ czas potrzebny na obliczenia związane z dziedziczeniem ma pewien wpływ na wydajność. Dziedziczenie wartości właściwości jest zwykle włączone tylko dla właściwości, w których określony scenariusz sugeruje, że dziedziczenie wartości właściwości jest odpowiednie. Można określić, czy właściwość zależności dziedziczy, przeglądając sekcję Informacje o właściwości zależności dla tej właściwości zależności w dokumentacji zestawu SDK.
Poniższy przykład przedstawia powiązanie i ustawia właściwość DataContext określającą źródło powiązania, które nie zostało pokazane we wcześniejszym przykładzie powiązania. Kolejne powiązania w podrzędnych obiektach nie muszą określać źródła; mogą korzystać z dziedziczonej wartości z DataContext w nadrzędnym obiekcie StackPanel. (Zamiast tego obiekt podrzędny może zdecydować się bezpośrednio określić własne DataContext lub Source w Bindingi celowo nie używać odziedziczonej wartości jako kontekstu danych jego powiązań).
<StackPanel Canvas.Top="50" DataContext="{Binding Source={StaticResource XmlTeamsSource}}">
<Button Content="{Binding XPath=Team/@TeamName}"/>
</StackPanel>
Aby uzyskać więcej informacji, zobacz Dziedziczenie wartości właściwości.
Integracja projektanta WPF
Kontrolka niestandardowa z właściwościami zaimplementowanymi jako właściwości zależności otrzyma odpowiednie wsparcie projektanta WPF w programie Visual Studio. Jednym z przykładów jest możliwość edytowania właściwości zależności bezpośrednich i dołączonych za pomocą okna właściwości . Aby uzyskać więcej informacji, zobacz Omówienie tworzenia kontrolek.
Pierwszeństwo wartości właściwości zależności
Po uzyskaniu wartości właściwości zależności potencjalnie uzyskujesz wartość ustawioną na tej właściwości za pomocą dowolnego z innych danych wejściowych opartych na właściwościach, które uczestniczą w systemie właściwości WPF. Preferencja wartości właściwości zależności istnieje, aby różne scenariusze uzyskiwania wartości przez właściwości mogły współdziałać w przewidywalny sposób.
Rozważmy poniższy przykład. Przykład zawiera styl, który ma zastosowanie do wszystkich przycisków i ich właściwości Background, ale następnie określa jeden przycisk z lokalnie ustawioną wartością Background.
Notatka
Dokumentacja zestawu SDK używa terminów "wartość lokalna" lub "lokalnie ustawiona wartość" od czasu do czasu podczas omawiania właściwości zależności. Lokalnie ustawiona wartość to wartość właściwości ustawiana bezpośrednio na wystąpieniu obiektu w kodzie lub jako atrybut elementu w języku XAML.
W zasadzie dla pierwszego przycisku właściwość jest ustawiana dwa razy, ale ma zastosowanie tylko jedna wartość: wartość o najwyższym pierwszeństwie. Wartość ustawiona lokalnie ma najwyższy priorytet (z wyjątkiem uruchomionej animacji, ale w tym przykładzie nie ma zastosowania animacja), a zatem lokalnie ustawiona wartość jest używana zamiast wartości ustawiającej styl tła na pierwszym przycisku. Drugi przycisk nie ma wartości lokalnej (i nie ma innej wartości o większym priorytecie niż zdefiniowana w stylu), dlatego tło w tym przycisku jest zaczerpnięte z definicji stylu.
<StackPanel>
<StackPanel.Resources>
<Style x:Key="{x:Type Button}" TargetType="{x:Type Button}">
<Setter Property="Background" Value="Red"/>
</Style>
</StackPanel.Resources>
<Button Background="Green">I am NOT red!</Button>
<Button>I am styled red</Button>
</StackPanel>
Dlaczego pierwszeństwo właściwości zależności istnieje?
Zazwyczaj nie chcesz, aby style zawsze stosować i ukrywać nawet lokalnie ustawioną wartość pojedynczego elementu (w przeciwnym razie trudno byłoby użyć stylów lub elementów w ogóle). W związku z tym wartości pochodzące ze stylów mają niższe pierwszeństwo niż wartość ustawiona lokalnie. Aby uzyskać bardziej szczegółową listę właściwości zależności oraz informacje, skąd może pochodzić ich efektywna wartość, zobacz Pierwszeństwo wartości właściwości zależności.
Notatka
Istnieje wiele właściwości zdefiniowanych w elementach WPF, które nie są właściwościami zależności. Ogólnie rzecz biorąc, właściwości były implementowane jako właściwości zależności tylko wtedy, gdy istniała potrzeba obsługi co najmniej jednego z scenariuszy obsługiwanych przez system właściwości: powiązanie danych, stylowanie, animacja, obsługa wartości domyślnej, dziedziczenie, właściwości dołączone lub unieważnienie.
Dowiedz się więcej o właściwościach zależności
Dołączona właściwość jest typem właściwości, która obsługuje wyspecjalizowaną składnię w języku XAML. Dołączona właściwość często nie ma bezpośredniej korespondencji z właściwością środowiska uruchomieniowego języka wspólnego (CLR) i niekoniecznie jest właściwością zależności. Typowym celem dołączonej właściwości jest umożliwienie elementom podrzędnym zgłaszania wartości właściwości do elementu nadrzędnego, nawet jeśli element nadrzędny i element podrzędny nie posiadają tej właściwości w ramach list składowych klasy. Jednym z podstawowych scenariuszy jest umożliwienie elementom podrzędnym informowania elementu nadrzędnego o tym, jak powinny być prezentowane w interfejsie użytkownika; aby zapoznać się z przykładem, zobacz Dock lub Left. Aby uzyskać szczegółowe informacje, zobacz Omówienie dołączonych właściwości.
Deweloperzy składników lub deweloperzy aplikacji mogą chcieć utworzyć własną właściwość zależności, aby umożliwić obsługę funkcji, takich jak powiązanie danych lub style, albo obsługa unieważnienia i wymuszania wartości. Aby uzyskać szczegółowe informacje, zobacz Niestandardowe właściwości zależności.
Traktuj właściwości zależności jako właściwości publiczne, dostępne lub wykrywalne dla każdego wywołującego, który ma dostęp do instancji. Aby uzyskać więcej informacji, zapoznaj się z Dependency Property Security.
Zobacz też
- właściwości zależności niestandardowych
- właściwości zależności Read-Only
- XAML w WPF
- architektura WPF
.NET Desktop feedback