Pierwszeństwo wartości właściwości zależności (WPF .NET)

Działanie systemu właściwości Windows Presentation Foundation (WPF) wpływa na wartość właściwości zależności. W tym artykule wyjaśniono, jak pierwszeństwo różnych danych wejściowych opartych na właściwościach w systemie właściwości WPF określa efektywną wartość właściwości zależności.

Ważne

Dokumentacja przewodnika dla komputerów dla platform .NET 7 i .NET 6 jest w budowie.

Wymagania wstępne

W tym artykule przyjęto założenie, że masz podstawową wiedzę na temat właściwości zależności i zapoznasz się z omówieniem właściwości zależności. Aby postępować zgodnie z przykładami w tym artykule, warto zapoznać się z językiem Extensible Application Markup Language (XAML) i wiedzieć, jak pisać aplikacje WPF.

System właściwości WPF

System właściwości WPF używa różnych czynników do określenia wartości właściwości zależności, takich jak walidacja właściwości w czasie rzeczywistym, późne powiązanie i powiadomienia o zmianie właściwości powiązanych. Mimo że kolejność i logika używana do określania wartości właściwości zależności jest złożona, uczenie się może pomóc uniknąć niepotrzebnych ustawień właściwości, a także dowiedzieć się, dlaczego próba ustawienia właściwości zależności nie spowodowało oczekiwanej wartości.

Właściwości zależności ustawione w wielu miejscach

Poniższy przykład XAML pokazuje, jak trzy różne operacje "set" we właściwości przycisku Background mogą mieć wpływ na jego wartość.

<StackPanel>
    <StackPanel.Resources>
        <ControlTemplate x:Key="ButtonTemplate" TargetType="{x:Type Button}">
            <Border Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}" 
                    BorderBrush="{TemplateBinding BorderBrush}">
                <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
            </Border>
        </ControlTemplate>
    </StackPanel.Resources>

    <Button Template="{StaticResource ButtonTemplate}" Background="Red">
        <Button.Style>
            <Style TargetType="{x:Type Button}">
                <Setter Property="Background" Value="Blue"/>
                <Style.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Background" Value="Yellow" />
                    </Trigger>
                </Style.Triggers>
            </Style>
        </Button.Style>
        Which color do you expect?
    </Button>
</StackPanel>

W tym przykładzie Background właściwość jest lokalnie ustawiona na Redwartość . Jednak niejawny styl zadeklarowany w zakresie przycisku próbuje ustawić Background właściwość na Blue. A gdy mysz znajduje się nad przyciskiem, wyzwalacz w niejawnych stylach próbuje ustawić Background właściwość na Yellow. Z wyjątkiem przymusu i animacji lokalnie ustawiona wartość właściwości ma najwyższy priorytet, więc przycisk będzie czerwony — nawet w przypadku myszy. Jeśli jednak usuniesz lokalnie ustawioną wartość z przycisku, zostanie ona pobrana Background z stylu. W obrębie stylu wyzwalacze mają pierwszeństwo, więc przycisk będzie żółty w myszy, a w przeciwnym razie niebieski. Przykład zastępuje wartość domyślną ControlTemplate przycisku, ponieważ szablon domyślny ma ustaloną wartość myszy Background .

Lista pierwszeństwa właściwości zależności

Poniższa lista to ostateczna kolejność pierwszeństwa używana przez system właściwości podczas przypisywania wartości środowiska uruchomieniowego do właściwości zależności. Najwyższy priorytet jest wymieniony jako pierwszy.

  1. Przymus systemu właściwości. Aby uzyskać więcej informacji na temat przymusu, zobacz Coercion i animacje.

  2. Aktywne animacje lub animacje z zachowaniem blokady. Aby mieć praktyczny efekt, wartość animacji musi mieć pierwszeństwo przed wartością podstawową (bez odpowiedzi), nawet jeśli wartość podstawowa została ustawiona lokalnie. Aby uzyskać więcej informacji, zobacz Coercion i animacje.

  3. Wartości lokalne. Wartość lokalną można ustawić za pomocą właściwości "otoki", która odpowiada ustawieniu atrybutu lub elementu właściwości w języku XAML lub przez wywołanie interfejsu SetValue API przy użyciu właściwości określonego wystąpienia. Wartość lokalna ustawiona za pomocą powiązania lub zasobu będzie miała taki sam priorytet jak wartość, która jest ustawiana bezpośrednio.

  4. TemplatedParent wartości właściwości szablonu. Element ma TemplatedParent wartość , jeśli została utworzona przez szablon (ControlTemplate lub DataTemplate). Aby uzyskać więcej informacji, zobacz TemplatedParent. W szablonie TemplatedParentokreślonym przez parametr kolejność pierwszeństwa to:

    1. Wyzwalaczy.

    2. Zestawy właściwości, zazwyczaj za pomocą atrybutów XAML.

  5. Niejawne style. Dotyczy tylko Style właściwości . Wartość Style to dowolny zasób stylu z wartością zgodną z typem TargetType elementu. Zasób stylu musi istnieć w obrębie strony lub aplikacji. Wyszukiwanie niejawnego zasobu stylu nie rozszerza się na zasoby stylów w motywach.

  6. Wyzwalacze stylu. Wyzwalacz stylu jest wyzwalaczem w jawnym lub niejawnym stylu. Styl musi istnieć w obrębie strony lub aplikacji. Wyzwalacze w stylach domyślnych mają niższy priorytet.

  7. Wyzwalacze szablonu. Wyzwalacz szablonu jest wyzwalaczem bezpośrednio zastosowanym szablonem lub szablonem w stylu. Styl musi istnieć w obrębie strony lub aplikacji.

  8. Wartości ustawiania stylów. Wartość ustawiająca styl jest wartością stosowana przez Setter styl. Styl musi istnieć w obrębie strony lub aplikacji.

  9. Style domyślne, znane również jako style motywu. Aby uzyskać więcej informacji, zobacz Style domyślne (motyw). W domyślnym stylu kolejność pierwszeństwa to:

    1. Aktywne wyzwalacze.

    2. Ustawiające.

  10. Dziedziczenie. Niektóre właściwości zależności elementu podrzędnego dziedziczą ich wartość z elementu nadrzędnego. Dlatego może nie być konieczne ustawienie wartości właściwości dla każdego elementu w całej aplikacji. Aby uzyskać więcej informacji, zobacz Dziedziczenie wartości właściwości.

  11. Wartość domyślna z metadanych właściwości zależności Właściwość zależności może mieć wartość domyślną ustawioną podczas rejestracji systemu właściwości tej właściwości. Klasy pochodne dziedziczące właściwość zależności mogą zastąpić metadane właściwości zależności (w tym wartość domyślna) dla poszczególnych typów. Aby uzyskać więcej informacji, zobacz Metadane właściwości zależności. W przypadku właściwości dziedziczonej wartość domyślna elementu nadrzędnego ma pierwszeństwo przed wartością domyślną elementu podrzędnego. Jeśli więc właściwość dziedziczona nie jest ustawiona, zostanie użyta domyślna wartość elementu głównego lub nadrzędnego zamiast wartości domyślnej elementu podrzędnego.

Szablonyparent

TemplatedParent pierwszeństwo nie ma zastosowania do właściwości elementów, które są deklarowane bezpośrednio w standardowym adiustacji aplikacji. Koncepcja TemplatedParent istnieje tylko dla elementów podrzędnych w drzewie wizualnym, które wchodzą w życie za pośrednictwem aplikacji szablonu. Gdy system właściwości przeszukuje szablon określony przez TemplatedParent wartość właściwości elementu, przeszukuje szablon, który utworzył element. Wartości właściwości z szablonu TemplatedParent zwykle działają tak, jakby były one lokalnie ustawiane wartości w elemencie, ale z mniejszym pierwszeństwem niż rzeczywiste wartości lokalne, ponieważ szablony są potencjalnie współużytkowane. W celu uzyskania więcej informacji, zobacz następujący temat: TemplatedParent.

Właściwość Style

Ta sama kolejność pierwszeństwa ma zastosowanie do wszystkich właściwości zależności, z wyjątkiem Style właściwości . Właściwość jest unikatowa Style w tym, że nie może być stylizowany. Wymuszanie lub animowanie Style właściwości nie jest zalecane (i animowanie Style właściwości wymaga niestandardowej klasy animacji). W związku z tym nie wszystkie elementy pierwszeństwa mają zastosowanie. Istnieją tylko trzy sposoby ustawiania Style właściwości:

  • Styl jawny. Style Właściwość elementu jest ustawiana bezpośrednio. Wartość Style właściwości działa tak, jakby była to wartość lokalna i ma taki sam pierwszeństwo jak element 3 na liście pierwszeństwa. W większości scenariuszy jawne style nie są zdefiniowane w tekście i zamiast tego są jawnie przywołyne jako zasób, na przykład Style="{StaticResource myResourceKey}".

  • Niejawny styl. Właściwość Style elementu nie jest ustawiana bezpośrednio. Zamiast tego styl jest stosowany, gdy istnieje na pewnym poziomie strony lub aplikacji, i ma klucz zasobu zgodny z typem elementu, którego dotyczy styl, na przykład <Style TargetType="x:Type Button">. Typ musi być dokładnie zgodny, na przykład <Style TargetType="x:Type Button"> nie zostanie zastosowany do MyButton typu, nawet jeśli MyButton pochodzi z Buttonklasy . Wartość Style właściwości ma taki sam priorytet jak element 5 na liście pierwszeństwa. Można wykryć niejawną wartość stylu, wywołując metodę DependencyPropertyHelper.GetValueSource , przekazując Style właściwość i sprawdzając ImplicitStyleReference wyniki.

  • Styl domyślny, znany również jako styl motywu. Właściwość Style elementu nie jest ustawiana bezpośrednio. Zamiast tego pochodzi z oceny motywu środowiska uruchomieniowego przez aparat prezentacji WPF. Przed środowiskiem uruchomieniowym Style wartość właściwości to null. Wartość Style właściwości ma taki sam priorytet jak element 9 na liście pierwszeństwa.

Style domyślne (motyw)

Każda kontrolka dostarczana z WPF ma domyślny styl, który może się różnić w zależności od motywu, dlatego styl domyślny jest czasami określany jako styl motywu.

Element ControlTemplate jest ważnym elementem w domyślnym stylu kontrolki. ControlTemplate jest wartością ustawiającą dla właściwości stylu Template . Jeśli style domyślne nie zawierają szablonu, kontrolka bez szablonu niestandardowego w ramach stylu niestandardowego nie będzie miała wyglądu wizualnego. Szablon nie tylko definiuje wygląd wizualizacji kontrolki, ale także definiuje połączenia między właściwościami w drzewie wizualnym szablonu i odpowiednią klasą sterowania. Każda kontrolka uwidacznia zestaw właściwości, które mogą wpływać na wygląd wizualizacji kontrolki bez zastępowania szablonu. Rozważmy na przykład domyślny wygląd kontrolki Thumb , która jest składnikiem ScrollBar .

Kontrolka Thumb ma pewne dostosowywalne właściwości. Domyślny szablon kontrolki Thumb tworzy podstawową strukturę lub drzewo wizualne z kilkoma zagnieżdżonym Border składnikami w celu utworzenia wyglądu skośnego. W szablonie właściwości, które mają być dostosowywane przez klasę Thumb , są udostępniane za pomocą szablonuBinding. Domyślny szablon kontrolki Thumb ma różne właściwości obramowania, które współużytkuje powiązanie szablonu z właściwościami, takimi jak Background lub BorderThickness. Jednak jeśli wartości właściwości lub ustaleń wizualnych są zakodowane w szablonie lub są powiązane z wartościami pochodzącymi bezpośrednio z motywu, można zmienić tylko te wartości, zastępując cały szablon. Ogólnie rzecz biorąc, jeśli właściwość pochodzi z szablonowego elementu nadrzędnego i nie jest uwidoczniona przez TemplateBindingelement , nie można zmienić wartości właściwości przez style, ponieważ nie ma wygodnego sposobu jej kierowania. Jednak ta właściwość może nadal mieć wpływ na dziedziczenie wartości właściwości w zastosowanym szablonie lub przez wartość domyślną.

Style domyślne określają TargetType wartości w definicjach. Ocena motywu środowiska uruchomieniowego pasuje TargetType do DefaultStyleKey domyślnego stylu do właściwości kontrolki. Natomiast zachowanie wyszukiwania w przypadku stylów niejawnych używa rzeczywistego typu kontrolki. Wartość DefaultStyleKey jest dziedziczona przez klasy pochodne, więc elementy pochodne, które w przeciwnym razie nie mają skojarzonego stylu, uzyskują domyślny wygląd wizualizacji. Jeśli na przykład pochodzisz MyButton z Buttonklasy , MyButton dziedziczy domyślny szablon .Button Klasy pochodne mogą zastąpić wartość domyślną metadanych DefaultStyleKey właściwości zależności. W związku z tym, jeśli chcesz innej reprezentacji wizualnej dla MyButtonprogramu , możesz zastąpić metadane właściwości zależności dla DefaultStyleKey elementu w MyButtonsystemie , a następnie zdefiniować odpowiedni styl domyślny, w tym szablon, który zostanie spakujesz za pomocą MyButton kontrolki. Aby uzyskać więcej informacji, zobacz Omówienie tworzenia kontrolek.

Zasób dynamiczny

Dynamiczne odwołania do zasobów i operacje powiązań mają pierwszeństwo przed lokalizacją, w której są ustawione. Na przykład zasób dynamiczny zastosowany do wartości lokalnej ma taki sam priorytet jak element 3 na liście pierwszeństwa. W innym przykładzie powiązanie zasobu dynamicznego zastosowane do klasy ustawiającej właściwości w stylu domyślnym ma taki sam pierwszeństwo jak element 9 na liście pierwszeństwa. Ponieważ dynamiczne odwołania do zasobów i powiązanie muszą pobierać wartości ze stanu środowiska uruchomieniowego aplikacji, proces określania pierwszeństwa wartości właściwości dla każdej danej właściwości rozszerza się na środowisko uruchomieniowe.

Odwołania do zasobów dynamicznych nie są technicznie częścią systemu właściwości i mają własną kolejność wyszukiwania, która współdziała z listą pierwszeństwa. Zasadniczo pierwszeństwo odwołań do zasobów dynamicznych to: element do strony głównej, aplikacji, motywu, a następnie systemu. Aby uzyskać więcej informacji, zobacz Zasoby XAML.

Mimo że odwołania do zasobów dynamicznych i powiązania mają pierwszeństwo przed lokalizacją, w której są ustawione, wartość jest odroczona. Jedną z konsekwencji jest to, że jeśli ustawisz zasób dynamiczny lub powiązanie z wartością lokalną, każda zmiana wartości lokalnej całkowicie zastępuje zasób dynamiczny lub powiązanie. Nawet jeśli wywołasz metodę ClearValue w celu wyczyszczenia wartości ustawionej lokalnie, zasób dynamiczny lub powiązanie nie zostaną przywrócone. W rzeczywistości, jeśli wywołasz ClearValue właściwość, która ma zasób dynamiczny lub powiązanie (bez wartości lokalnej literału), zasób dynamiczny lub powiązanie zostaną wyczyszczone.

SetCurrentValue

Metoda SetCurrentValue to inny sposób ustawiania właściwości, ale nie znajduje się na liście pierwszeństwa. SetCurrentValue Umożliwia zmianę wartości właściwości bez zastępowania źródła poprzedniej wartości. Jeśli na przykład właściwość jest ustawiana przez wyzwalacz, a następnie przypiszesz inną wartość przy użyciu SetCurrentValuemetody , następna akcja wyzwalacza ustawi właściwość z powrotem na wartość wyzwalacza. Możesz użyć SetCurrentValue zawsze, gdy chcesz ustawić wartość właściwości bez podawania tej wartości na poziomie pierwszeństwa wartości lokalnej. Podobnie można użyć SetCurrentValue polecenia , aby zmienić wartość właściwości bez zastępowania powiązania.

Przymus i animacja

Przymus i animacja działają zarówno na wartości bazowej. Wartość podstawowa to wartość właściwości zależności o najwyższym prioryencie określonym przez ocenę w górę przez listę pierwszeństwa do momentu osiągnięcia elementu 2.

Jeśli animacja nie określa zarówno wartości właściwości, jak From i To dla niektórych zachowań lub jeśli animacja celowo przywraca wartość podstawową po zakończeniu, wartość podstawowa może mieć wpływ na animowaną wartość. Aby to zobaczyć w praktyce, uruchom przykładową aplikację Wartości docelowe. W przykładzie dla wysokości prostokąta spróbuj ustawić początkowe wartości lokalne, które różnią się od dowolnej From wartości. Przykładowe animacje zaczynają się od razu przy użyciu From wartości zamiast wartości podstawowej. Stop Określając jako wartość , po zakończeniu FillBehavioranimacja zresetuje wartość właściwości na wartość podstawową. Normalny pierwszeństwo jest używane do określania wartości bazowej po zakończeniu animacji.

Do jednej właściwości można zastosować wiele animacji, a każda animacja ma inny pierwszeństwo. Zamiast stosować animację z najwyższym priorytetem, aparat prezentacji WPF może składać wartości animacji, w zależności od sposobu definiowania animacji i typu animowanych wartości. Aby uzyskać więcej informacji, zobacz Omówienie animacji.

Przymus znajduje się w górnej części listy pierwszeństwa. Nawet uruchomiona animacja podlega przymusowi wartości. Niektóre istniejące właściwości zależności w WPF mają wbudowane przymus. W przypadku właściwości zależności niestandardowych można zdefiniować zachowanie przymusu, zapisując CoerceValueCallback element przekazywany jako część metadanych podczas tworzenia właściwości. Można również zastąpić zachowanie wymuszania istniejących właściwości, przesłaniając metadane dla tej właściwości w klasie pochodnej. Przymus wchodzi w interakcję z wartością bazową w taki sposób, że ograniczenia przymusu są stosowane w miarę ich istnienia w tym czasie, ale wartość podstawowa jest nadal zachowywana. W rezultacie, jeśli ograniczenia przymusu zostaną później zniesione, przymus zwróci najbliższą wartość możliwą do wartości bazowej, a potencjalnie wpływ przymusu na właściwość przestanie obowiązywać, gdy tylko wszystkie ograniczenia zostaną zniesione. Aby uzyskać więcej informacji na temat zachowania przymusu, zobacz Wywołania zwrotne i walidacja właściwości zależności.

Zachowania wyzwalacza

Kontrolki często definiują zachowania wyzwalacza w ramach ich stylu domyślnego. Ustawienie właściwości lokalnych kontrolek może potencjalnie powodować konflikt z tymi wyzwalaczami, uniemożliwiając wyzwalacze reagowania (wizualnie lub behawioralnie) na zdarzenia sterowane przez użytkownika. Typowym zastosowaniem wyzwalacza właściwości jest kontrolowanie właściwości stanu, takich jak IsSelected lub IsEnabled. Na przykład, gdy element Button jest wyłączony, wyzwalacz stylu motywu (IsEnabled to false) ustawia Foreground wartość, aby wyglądała Button na wyszarzone. Jeśli ustawiono wartość lokalną Foreground , wyższa wartość właściwości lokalnej pierwszeństwa spowoduje zastąpienie wartości stylu Foreground motywu, nawet jeśli wartość jest wyłączona Button . Podczas ustawiania wartości właściwości, które zastępują zachowania wyzwalacza na poziomie motywu dla kontrolki, należy zachować ostrożność, aby nie zakłócać zamierzonego środowiska użytkownika dla tej kontrolki.

Clearvalue

Metoda ClearValue czyści dowolną lokalnie zastosowaną wartość właściwości zależności dla elementu. Jednak wywołanie ClearValue nie gwarantuje, że wartość domyślna ustanowiona w metadanych podczas rejestracji właściwości jest nową obowiązującą wartością. Wszyscy inni uczestnicy listy pierwszeństwa są nadal aktywni i usuwana jest tylko lokalnie ustawiona wartość. Jeśli na przykład wywołasz ClearValue właściwość, która ma styl motywu, wartość stylu motywu zostanie zastosowana jako nowa wartość, a nie domyślna oparta na metadanych. Jeśli chcesz ustawić wartość właściwości na wartość domyślną zarejestrowanych metadanych, pobierz domyślną wartość metadanych, wykonując zapytanie dotyczące metadanych właściwości zależności, a następnie lokalnie ustaw wartość właściwości za pomocą wywołania na SetValue.

Zobacz też