Sdílet prostřednictvím


Priorita hodnot závislých vlastností

Toto téma vysvětluje, jak práce systému vlastností Windows Presentation Foundation (WPF) mohou ovlivnit hodnotu vlastnosti závislosti a popisuje prioritu, podle kterých aspektů systému vlastností se vztahují na efektivní hodnotu vlastnosti.

Předpoklady

V tomto tématu se předpokládá, že rozumíte vlastnostem závislostí z pohledu příjemce existujících vlastností závislostí na třídách WPF a máte přehled vlastností závislostí. Abyste mohli postupovat podle příkladů v tomto tématu, měli byste také rozumět XAML a vědět, jak psát aplikace WPF.

Systém vlastností WPF

Systém vlastností WPF nabízí účinný způsob, jak mít hodnotu vlastností závislostí určit různými faktory, což umožňuje funkce, jako je ověřování vlastností v reálném čase, pozdní vazba a upozorňování souvisejících vlastností na změny hodnot pro jiné vlastnosti. Přesné pořadí a logika, které se používají k určení hodnot vlastností závislostí, jsou přiměřeně složité. Znalost tohoto pořadí vám pomůže vyhnout se nepotřebným nastavením vlastnosti a může také zmást nejasnosti ohledně toho, proč se některé pokusy o ovlivnění nebo předvídání hodnoty vlastnosti závislosti nevykončily, což vede k očekávané hodnotě.

Vlastnosti závislosti můžou být nastaveny na více místech.

Následuje příklad XAML, kde stejná vlastnost (Background) má tři různé operace set, které mohou ovlivnit hodnotu.

<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>

Jakou barvu očekáváte, bude platit červená, zelená nebo modrá?

S výjimkou animovaných hodnot a převodu jsou místní sady vlastností nastaveny na nejvyšší prioritu. Pokud nastavíte hodnotu místně, můžete očekávat, že se tato hodnota bude respektovat, a to i nad všemi styly nebo šablonami ovládacích prvků. V tomto příkladu Background je nastavená možnost Red místně. Proto styl definovaný v tomto oboru, i když jde o implicitní styl, který by jinak platil pro všechny prvky tohoto typu v tomto oboru, není nejvyšší prioritou pro poskytnutí Background vlastnosti jeho hodnoty. Pokud jste z instance tlačítka odebrali místní hodnotu Red, měl by mít tento styl přednost a tlačítko by získalo hodnotu Pozadí ze stylu. Ve stylu mají triggery přednost, takže tlačítko bude modré, pokud je nad ním myš, a jinak zelené.

Seznam priorit nastavení vlastností závislosti

Následuje konečné pořadí, které systém vlastností používá při přiřazování hodnot závislostí za běhu. Nejvyšší priorita je uvedena jako první. Tento seznam se rozšiřuje o některé zobecnění provedených v přehledu vlastností závislosti.

  1. Převod systému vlastností. Podrobnosti o převodu naleznete v části Převod, Animace a Základní hodnota dále v tomto tématu.

  2. Aktivní animace nebo animace s chováním přidržet Aby bylo možné mít jakýkoli praktický účinek, musí mít animace vlastnosti přednost před základní (neanimovanou) hodnotou, i když byla tato hodnota nastavena místně. Podrobnosti najdete v části Převod, Animace a Základní hodnota dále v tomto tématu.

  3. Místní hodnota. Místní hodnota může být nastavena prostřednictvím pohodlí "obálky" vlastnost, která se také rovná nastavení jako atribut nebo element vlastnosti v XAML, nebo voláním SetValue rozhraní API pomocí vlastnosti konkrétní instance. Pokud nastavíte místní hodnotu pomocí vazby nebo prostředku, každá z nich bude mít přednost, jako by byla nastavena přímá hodnota.

  4. TemplatedParent – vlastnosti šablony Prvek obsahuje TemplatedParent , pokud byl vytvořen jako součást šablony (a ControlTemplate nebo DataTemplate). Podrobnosti o tom, kdy se to týká, najdete v části TemplatedParent dále v tomto tématu. V šabloně platí následující priorita:

    1. Triggery ze TemplatedParent šablony.

    2. Sady vlastností (obvykle prostřednictvím atributů XAML) v TemplatedParent šabloně.

  5. Implicitní styl Platí pouze pro Style vlastnost. Vlastnost Style je vyplněna libovolným prostředkem stylu klíčem, který odpovídá typu daného prvku. Tento prostředek stylu musí existovat buď na stránce, nebo v aplikaci; Vyhledávání pro prostředek implicitního stylu nepokračuje v motivech.

  6. Aktivační události stylu Triggery v rámci stylů ze stránky nebo aplikace (tyto styly můžou být explicitní nebo implicitní styly, ale ne z výchozích stylů, které mají nižší prioritu).

  7. Triggery šablon Libovolný trigger ze šablony ve stylu nebo přímo použitá šablona.

  8. Šablony stylů. Hodnoty ze stylů ze Setter stránky nebo aplikace

  9. Výchozí styl (motiv). Podrobnosti o tom, kdy se to týká, a o tom, jak styly motivu souvisejí se šablonami v rámci stylů motivu, najdete v části Výchozí styly (motiv) dále v tomto tématu. Ve výchozím stylu platí následující pořadí priorit:

    1. Aktivní triggery ve stylu motivu

    2. Setters ve stylu motivu.

  10. Dědičnosti. Několik vlastností závislosti dědí své hodnoty z nadřazeného elementu do podřízených elementů, aby nemusely být nastaveny speciálně pro každý prvek v celé aplikaci. Podrobnosti naleznete v tématu Dědičnost hodnot vlastností.

  11. Výchozí hodnota z metadat vlastností závislostí Každá daná vlastnost závislosti může mít výchozí hodnotu stanovenou registrací systému vlastností dané konkrétní vlastnosti. Odvozené třídy, které dědí vlastnost závislosti mají možnost přepsat metadata (včetně výchozí hodnoty) na základě jednotlivých typů. Další informace najdete v tématu Metadata vlastností závislostí . Vzhledem k tomu, že dědičnost je zaškrtnutá před výchozí hodnotou, u zděděné vlastnosti má výchozí hodnota nadřazeného elementu přednost před podřízeným elementem. V důsledku toho, pokud zděděná vlastnost není nastavena kdekoli, výchozí hodnota zadaná v kořenové nebo nadřazené hodnotě se použije místo výchozí hodnoty podřízeného elementu.

TemplatedParent

TemplatedParent jako položka priority se nevztahuje na žádnou vlastnost prvku, který deklarujete přímo ve standardním kódu aplikace. Koncept TemplatedParent existuje pouze pro podřízené položky v rámci vizuálního stromu, který přichází do existence prostřednictvím aplikace šablony. Když systém vlastností hledá TemplatedParent v šabloně hodnotu, hledá šablonu, která vytvořila tento prvek. Hodnoty vlastností ze TemplatedParent šablony obecně fungují, jako by byly nastaveny jako místní hodnota podřízeného prvku, ale tato menší priorita oproti místní hodnotě existuje, protože šablony jsou potenciálně sdíleny. Podrobnosti najdete v tématu TemplatedParent.

The Style Property

Pořadí vyhledávání popsané výše platí pro všechny možné vlastnosti závislostí s výjimkou jedné: Style vlastnosti. Vlastnost Style je jedinečná v tom, že nemůže být sama o sobě stylována, takže přednost položky 5 až 8 se nevztahují. Také se nedoporučuje animování nebo vynucení Style (a animování Style by vyžadovalo vlastní třídu animací). Tato možnost ponechá tři způsoby, jak Style může být vlastnost nastavena:

  • Explicitní styl Vlastnost Style je nastavena přímo. Ve většině scénářů není styl definován jako vložený, ale místo toho se odkazuje jako na prostředek explicitním klíčem. V tomto případě samotná vlastnost Style funguje, jako by se jednalo o místní hodnotu, prioritu položky 3.

  • Implicitní styl Vlastnost Style není nastavena přímo. Existuje Style však na určité úrovni v sekvenci vyhledávání prostředků (stránka, aplikace) a je klíčován pomocí klíče prostředku, který odpovídá typu, na který se má styl použít. V tomto případě samotná Style vlastnost působí podle priority identifikované v pořadí jako položka 5. Tuto podmínku Style lze zjistit pomocí DependencyPropertyHelper vlastnosti a vyhledáním ImplicitStyleReference výsledků.

  • Výchozí styl, označovaný také jako styl motivu. Vlastnost Style není nastavena přímo a ve skutečnosti se bude číst jako null až do doby běhu. V tomto případě styl pochází z vyhodnocení motivu za běhu, který je součástí prezentačního modulu WPF.

Pro implicitní styly, které nejsou v motivech, musí typ přesně odpovídat - odvozená MyButtonButtontřída nebude implicitně používat styl pro Button.

Výchozí styly (motiv)

Každý ovládací prvek, který se dodává s WPF, má výchozí styl. Tento výchozí styl se může lišit podle motivu, což je důvod, proč se tento výchozí styl někdy označuje jako styl motivu.

Nejdůležitější informace, které jsou nalezeny ve výchozím stylu ovládacího prvku, je jeho šablona ovládacího prvku, která existuje ve stylu motivu jako setter pro jeho Template vlastnost. Pokud nebyla žádná šablona z výchozích stylů, ovládací prvek bez vlastní šablony jako součást vlastního stylu by neměl vůbec žádný vizuální vzhled. Šablona z výchozího stylu poskytuje vizuální vzhled každého ovládacího prvku základní strukturu a také definuje propojení mezi vlastnostmi definovanými ve vizuálním stromu šablony a odpovídající třídou ovládacího prvku. Každý ovládací prvek zpřístupňuje sadu vlastností, které můžou ovlivnit vzhled ovládacího prvku bez úplné nahrazení šablony. Představte si například výchozí vzhled Thumb ovládacího prvku, který je součástí ScrollBarovládacího prvku .

A Thumb má určité přizpůsobitelné vlastnosti. Výchozí šablona objektu Thumb vytvoří základní strukturu / vizuální strom s několika vnořenými Border komponentami a vytvoří zkosený vzhled. Pokud je vlastnost, která je součástí šablony, určena k zveřejnění pro přizpůsobení Thumb třídou, pak tato vlastnost musí být vystavena TemplateBinding v rámci šablony. V případě Thumb, že různé vlastnosti těchto ohraničení sdílejí vazbu šablony s vlastnostmi, jako BackgroundBorderThicknessje nebo . Některé jiné vlastnosti nebo vizuální uspořádání jsou pevně zakódované do šablony ovládacího prvku nebo jsou vázány na hodnoty, které pocházejí přímo z motivu, a nelze změnit zkratku nahrazení celé šablony. Obecně platí, že pokud vlastnost pochází z nadřazeného objektu šablony a není vystavena vazbou šablony, nelze ji upravit styly, protože neexistuje snadný způsob, jak je cílit. Tato vlastnost ale může být stále ovlivněna dědičností hodnot vlastností v použité šabloně nebo výchozí hodnotou.

Styly motivu používají jako klíč v definicích typ. Pokud se však motivy použijí na danou instanci elementu, motivy vyhledávání tohoto typu se provádí kontrolou DefaultStyleKey vlastnosti ovládacího prvku. To je na rozdíl od použití literálového typu jako implicitních stylů. Hodnota DefaultStyleKey zdědí odvozené třídy, i když implementátor ho nezměnil (zamýšlený způsob změny vlastnosti není přepsán na úrovni vlastnosti, ale změnit jeho výchozí hodnotu v metadatech vlastnosti). Tato nepřímost umožňuje základní třídy definovat styly motivu pro odvozené prvky, které jinak nemají styl (nebo důležitější je, že nemají šablonu v tomto stylu, a proto by neměla vůbec žádný výchozí vizuální vzhled). Proto můžete odvodit MyButtonButton výchozí šablonu a přesto ji získat Button . Pokud jste byli autorem MyButton ovládacího prvku a chtěli jste jiné chování, můžete přepsat metadata vlastností závislostí DefaultStyleKeyMyButton , aby vrátila jiný klíč, a pak definovat relevantní styly motivu včetně šablony, pro MyButton kterou je nutné zabalit s ovládacím MyButton prvku. Další podrobnosti o motivech, stylech a vytváření ovládacích prvků najdete v tématu Přehled vytváření ovládacích prvků.

Dynamické odkazy na prostředky a vazby

Dynamické odkazy na prostředky a operace vazby respektují prioritu umístění, ve kterém jsou nastavené. Například dynamický prostředek použitý na místní hodnotu funguje podle položky priority 3, vazba pro setter vlastnosti v rámci stylu motivu se vztahuje na položku priority 9 atd. Vzhledem k tomu, že dynamické odkazy na prostředky a vazby musí být schopny získat hodnoty ze stavu běhu aplikace, znamená to, že skutečný proces určení priority hodnoty vlastnosti pro všechny dané vlastnosti se rozšíří i do doby běhu.

Dynamické odkazy na prostředky nejsou výhradně součástí systému vlastností, ale mají vlastní pořadí vyhledávání, které interaguje s posloupností uvedenou výše. Tato priorita je podrobněji zdokumentovaná v prostředcích XAML. Základní součet této priority je: element na kořen stránky, aplikace, motiv, systém.

Dynamické prostředky a vazby mají přednost před nastavením, ale hodnota se odloží. Jedním z těchto důsledků je, že pokud nastavíte dynamický prostředek nebo vazbu na místní hodnotu, jakákoli změna místní hodnoty nahradí dynamický prostředek nebo vazbu zcela. I když zavoláte metodu ClearValue , která vymaže hodnotu místně nastavené, dynamický prostředek nebo vazba se neobnoví. Ve skutečnosti, pokud voláte ClearValue vlastnost, která má dynamický prostředek nebo vazbu na místě (bez literálové místní hodnoty), vymažou ClearValue se také voláním.

SetCurrentValue

Metoda SetCurrentValue je další způsob, jak nastavit vlastnost, ale není v pořadí priorit. SetCurrentValue Místo toho můžete změnit hodnotu vlastnosti bez přepsání zdroje předchozí hodnoty. Můžete použít SetCurrentValue libovolný čas, který chcete nastavit, aniž byste tuto hodnotu dali přednost místní hodnotě. Pokud je například vlastnost nastavena triggerem a pak přiřazena další hodnotu prostřednictvím SetCurrentValue, systém vlastností stále respektuje aktivační událost a vlastnost se změní, pokud dojde k akci triggeru. SetCurrentValue umožňuje změnit hodnotu vlastnosti bez poskytnutí zdroje s vyšší prioritou. Podobně můžete použít SetCurrentValue ke změně hodnoty vlastnosti bez přepsání vazby.

Převod, animace a základní hodnota

Převod i animace fungují na hodnotě, která se v této sadě SDK označuje jako "základní hodnota". Základní hodnota je tedy libovolná hodnota určena vyhodnocením směrem nahoru v položkách, dokud se nedosáhne položky 2.

U animace může mít základní hodnota vliv na animovanou hodnotu, pokud tato animace pro určité chování neurčuje "Od" a "Komu" nebo pokud se animace po dokončení záměrně vrátí k základní hodnotě. Pokud si to chcete prohlédnout v praxi, spusťte ukázku cílových hodnot Od, Do a Podle animace. Zkuste nastavit místní hodnoty výšky obdélníku v příkladu tak, aby se počáteční místní hodnota v animaci liší od hodnoty "Od". Všimněte si, že animace začínají hned pomocí hodnot Od a po spuštění nahraďte základní hodnotu. Animace může určit, aby se vrátila k hodnotě nalezené před animací, jakmile je dokončena zadáním zarážky FillBehavior. Následně se pro stanovení základní hodnoty použije normální priorita.

U jedné vlastnosti může být použito více animací, přičemž každá z těchto animací byla pravděpodobně definována z různých bodů v prioritě hodnoty. Tyto animace ale potenciálně sloučí jejich hodnoty, a ne jen použije animaci z vyšší priority. To závisí přesně na tom, jak jsou animace definovány, a na typu hodnoty, která se animuje. Další informace o animaci vlastností naleznete v tématu Přehled animace.

Převod platí na nejvyšší úrovni všech. Dokonce i spuštěná animace podléhá převodu hodnot. Některé existující vlastnosti závislostí ve WPF mají integrovaný převod. U vlastní vlastnosti závislosti definujete chování při převodu vlastní vlastnosti závislosti tak, že při vytváření vlastnosti zapíšete CoerceValueCallback a předáte zpětné volání jako součást metadat. Můžete také přepsat chování převodu existujících vlastností přepsáním metadat této vlastnosti v odvozené třídě. Převod interaguje se základní hodnotou takovým způsobem, že se omezení při převodu použijí, protože tato omezení existují v době, ale základní hodnota je stále zachována. Proto pokud jsou omezení v převodu později zrušena, vrátí převod nejbližší možnou hodnotu této základní hodnoty a potenciálně vliv na převod na vlastnost přestane, jakmile budou všechna omezení zrušena. Další informace o chování při převodu naleznete v tématu Zpětné volání vlastností závislostí a ověřování.

Chování triggerů

Ovládací prvky často definují chování triggerů jako součást jejich výchozího stylu v motivech. Nastavení místních vlastností u ovládacích prvků může zabránit tomu, aby triggery mohly reagovat na události řízené uživatelem vizuálně nebo chováním. Nejběžnějším použitím triggeru vlastnosti je řízení nebo vlastnosti stavu, například IsSelected. Například když je ve výchozím nastavení zakázaná Button (trigger pro IsEnabledfalse) Foreground je hodnota ve stylu motivu, je to, co způsobí, že se ovládací prvek zobrazí "šedě". Pokud jste ale nastavili místní Foreground hodnotu, bude tato normální barva šedé přerušována podle priority vaší místní sadou vlastností, a to i v tomto scénáři aktivované vlastností. Buďte opatrní při nastavování hodnot pro vlastnosti, které mají chování triggeru na úrovni motivu, a ujistěte se, že nejste neoprávněně zasahující do zamýšleného uživatelského prostředí pro tento ovládací prvek.

ClearValue a priorita hodnot

Metoda ClearValue poskytuje urychlené prostředky k vymazání jakékoli místně použité hodnoty z vlastnosti závislosti, která je nastavena na elementu. Volání ClearValue však není zárukou, že výchozí hodnota vytvořená v metadatech během registrace vlastnosti je nová efektivní hodnota. Všichni ostatní účastníci v prioritě hodnot jsou stále aktivní. Z pořadí priorit byla odebrána pouze místně nastavená hodnota. Pokud například voláte ClearValue vlastnost, ve které je tato vlastnost nastavena také stylem motivu, použije se hodnota motivu jako nová hodnota místo výchozího nastavení založeného na metadatech. Pokud chcete všechny účastníky hodnoty vlastnosti převést z procesu a nastavit hodnotu na výchozí zaregistrovaná metadata, můžete tuto výchozí hodnotu získat konečným dotazem na metadata vlastnosti závislosti a pak můžete použít výchozí hodnotu k místnímu nastavení vlastnosti s voláním SetValue.

Viz také