Sdílet prostřednictvím


Pokyny pro navrhování stylovatelných ovládacích prvků

Tento dokument shrnuje sadu osvědčených postupů, které je potřeba zvážit při návrhu ovládacího prvku, který chcete snadno stylizovat a šablonovat. Tuto sadu osvědčených postupů jsme vytvořili mnoha pokusy a omyly při práci na stylech ovládacích prvků tématu pro sadu integrovaných ovládacích prvků WPF. Dozvěděli jsme se, že úspěšný styl je stejně funkcí dobře navrženého objektového modelu, jako je samotný styl. Zamýšlenou cílovou skupinou pro tento dokument je autor ovládacího prvku, nikoli autor stylu.

Terminologie

Styling a šablonování odkazují na sadu technologií, které umožňují autorovi ovládacího prvku odložit vizuální aspekty ovládacího prvku na styl a šablonu ovládacího prvku. Tato sada technologií zahrnuje:

  • Styly (včetně nastavovatelů vlastností, spouštěčů a rozvržení animací)

  • Prostředky.

  • Šablony ovládacích prvků

  • Šablony dat.

Úvod k stylům a šablonování najdete v tématu Styling a Šablonování.

Než začnete: Pochopení ovládacího prvku

Než se pustíte do těchto pokynů, je důležité pochopit a definovat běžné používání ovládacího prvku. Styling odhaluje často chaotickou sadu možností. Ovládací prvky navržené pro široké použití (v mnoha aplikacích, mnoha vývojáři) čelí výzvě, že úprava stylů může způsobit rozsáhlé změny vizuálního vzhledu ovládacího prvku. Ve skutečnosti se stylovaný ovládací prvek nemusí ani podobat záměrům autora ovládacího prvku. Vzhledem k tomu, že flexibilita, kterou styling nabízí, je v podstatě neomezená, můžete použít myšlenku společného použití, která vám pomůže určit rozsah rozhodnutí.

Abyste pochopili běžné použití ovládacího prvku, je vhodné uvažovat o hodnotové nabídce ovládacího prvku. Co váš ovládací prvek nabízí, co žádný jiný nemůže nabídnout? Běžné použití neznamená žádný konkrétní vizuální vzhled, ale spíše filozofie ovládacího prvku a přiměřenou sadu očekávání o jeho použití. Toto porozumění vám umožní provést určité předpoklady o modelu složení a chování definované stylem ovládacího prvku v běžném případě. V případě ComboBoxvám například pochopení běžného použití neudělí žádný přehled o tom, jestli má konkrétní ComboBox zaoblené rohy, ale poskytne vám přehled o tom, že ComboBox pravděpodobně potřebuje vyskakovací okno a nějakou možnost přepnutí, jestli je otevřené.

Obecné pokyny

  • Nesnažte se přísně vynucovat šablonové smlouvy. Kontrakt šablony ovládacího prvku se může skládat z prvků, příkazů, vazeb, triggerů nebo dokonce nastavení vlastností, které jsou požadovány nebo očekávány pro správné fungování ovládacího prvku.

    • Co nejvíce minimalizujte kontrakty.

    • Návrh kolem očekávání, že během návrhu (tj. při použití nástroje pro návrh) je běžné, že šablona ovládacího prvku bude v neúplném stavu. WPF nenabízí infrastrukturu pro stav „skládání“, takže ovládací prvky musí být sestaveny s očekáváním, že takový stav může být platný.

    • Nevyvolávejte výjimky, pokud není dodržen žádný aspekt kontraktu šablony. V tomto smyslu by panely neměly vyvolávat výjimky, pokud mají příliš mnoho nebo příliš málo prvků.

  • Zahrňte periferní funkce do pomocných prvků šablony. Každý ovládací prvek by se měl zaměřit na jeho základní funkce a skutečnou hodnotu a definovat běžné použití ovládacího prvku. Za tímto účelem použijte skládání a pomocné prvky v šabloně k povolení periferního chování a vizualizací, tedy těm, které nepřispívají k základní funkčnosti ovládacího prvku. Pomocné prvky spadají do tří kategorií:

    • samostatné typy pomocných rutin jsou veřejné a opakovaně použitelné ovládací prvky nebo primitivy, které se používají "anonymně" v šabloně, což znamená, že pomocný prvek ani stylovaný ovládací prvek si druhý prvek neuvědomuje. Technicky vzato může být libovolný prvek anonymním typem, ale v tomto kontextu termín popisuje typy, které zapouzdřují specializované funkce umožňující cílené scénáře.

    • pomocné prvky založené na typu jsou nové typy, které zapouzdřují specializované funkce. Tyto prvky jsou obvykle navrženy s užším rozsahem funkcí než běžné ovládací prvky nebo primitivy. Na rozdíl od samostatných pomocných prvků jsou pomocné prvky založené na typech vědomy kontextu, ve kterém se používají, a obvykle musí sdílet data s ovládacím prvku, do jehož šablony patří.

    • Pomocné prvky, které jsou pojmenované, jsou běžné ovládací prvky nebo primitivy, které ovládací prvek očekává, že najde v rámci šablony podle jména. Tyto prvky mají v šabloně dobře známý název, takže ovládací prvek může najít prvek a interagovat s ním programově. V libovolné šabloně může být pouze jeden prvek s daným názvem.

    V následující tabulce jsou uvedeny pomocné prvky používané styly ovládacích prvků dnes (tento seznam není vyčerpávající):

    Prvek Typ Používáno kým
    ContentPresenter Na základě typu Button, CheckBox, RadioButton, Frameatd. (všechny typy ContentControl)
    ItemsPresenter Na základě typu ListBox, ComboBox, Menuatd. (všechny typy ItemsControl)
    ToolBarOverflowPanel pojmenovaný ToolBar
    Popup Samostatný ComboBox, ToolBar, Menu, ToolTipatd.
    RepeatButton Pojmenovaný Slider, ScrollBara tak dále
    ScrollBar Pojmenovaný ScrollViewer
    ScrollViewer Samostatný ListBox, ComboBox, Menu, Framea tak dále
    TabPanel Samostatný TabControl
    TextBox Pojmenovaný ComboBox
    TickBar Na základě typu Slider
  • minimalizovat požadované vazby zadané uživatelem nebo nastavení vlastností u pomocných prvků. Pomocný prvek obvykle vyžaduje určité vazby nebo nastavení vlastností, aby správně fungoval v šabloně ovládacího prvku. Pomocný prvek a šablonový ovládací prvek by měly co nejvíce nastavit tato nastavení. Při nastavování vlastností nebo vytváření vazeb je třeba dbát na to, aby nebyly přepsány hodnoty nastavené uživatelem. Konkrétní osvědčené postupy jsou následující:

    • Pojmenované pomocné prvky by měly být identifikovány nadřazeným prvkem a nadřazený prvek by měl navázat všechna požadovaná nastavení v pomocném prvku.

    • Pomocné prvky založené na typu by měly na sobě přímo nastavit požadovaná nastavení. To může vyžadovat, aby se pomocný prvek dotazoval na kontext informací, ve kterém se používá, včetně jeho TemplatedParent (typ ovládacího prvku šablony, ve které se používá). Například ContentPresenter automaticky propojí vlastnost Content svého TemplatedParent s vlastností Content, když je použito v odvozeném typu ContentControl.

    • Samostatné pomocné elementy nelze tímto způsobem optimalizovat, protože podle definice ani pomocný prvek ani nadřazený prvek o druhém neví.

  • Použijte vlastnost Název k označení prvků v šabloně. Ovládací prvek, který potřebuje najít prvek ve svém stylu, aby k němu měl programový přístup, by to měl provést pomocí vlastnosti Name a paradigmatu FindName. Ovládací prvek by neměl vyvolat výjimku, pokud prvek nebyl nalezen, ale bezobslužně a elegantně zakázat funkce, které tento prvek vyžadovaly.

  • Použijte osvědčené postupy pro vyjádření stavu řízení a chování ve stylu. Následuje seřazený seznam osvědčených postupů pro vyjádření změn stavu řízení a chování ve stylu. Měli byste použít první položku v seznamu, která umožňuje váš scénář.

    1. Vazba vlastností. Příklad: vazba mezi ComboBox.IsDropDownOpen a ToggleButton.IsChecked.

    2. Aktivované změny vlastností nebo animace vlastností Příklad: stav najetí myší u Button.

    3. Příkaz. Příklad: LineUpCommand / LineDownCommand v ScrollBar.

    4. Samostatné pomocné prvky. Příklad: TabPanel v TabControl.

    5. Pomocné typy založené na typech Příklad: ContentPresenter v Button, TickBar v Slider.

    6. Pojmenované pomocné prvky Příklad: TextBox v ComboBox.

    7. Bublinové události z pojmenovaných pomocných typů Pokud nasloucháte bublinovým událostem z elementu stylu, měli byste vyžadovat, aby byl prvek generující událost jednoznačně identifikován. Příklad: Thumb v ToolBar.

    8. Vlastní chování OnRender Příklad: ButtonChrome v Button.

  • Používejte triggery stylu (na rozdíl od triggerů šablon) střídmě. Triggery, které ovlivňují vlastnosti prvků v šabloně, musí být deklarovány v šabloně. Triggery, které ovlivňují vlastnosti ovládacího prvku (bez TargetName), mohou být deklarovány ve stylu, pokud nevíte, že změna šablony by měla také zničit trigger.

  • Být konzistentní s existujícími vzory stylů. Často existuje několik způsobů, jak problém vyřešit. Mějte na paměti existující styly ovládacích prvků a v případě možností je dodržujte konzistentně. To je zvlášť důležité pro ovládací prvky, které jsou odvozeny ze stejného základního typu (například ContentControl, ItemsControl, RangeBaseatd.).

  • Zpřístupnění vlastností umožňující běžné scénáře přizpůsobení bez nutnosti přešablonování. WPF nepodporuje připojitelné/přizpůsobitelné části, takže uživatel ovládacího prvku zůstává pouze se dvěma metodami přizpůsobení: nastavení vlastností přímo nebo nastavení vlastností pomocí stylů. S ohledem na to je vhodné vytvořit omezený počet vlastností cílených na velmi běžné scénáře přizpůsobení s vysokou prioritou, které by jinak vyžadovaly opakování. Tady jsou osvědčené postupy pro případy, kdy a jak povolit scénáře přizpůsobení:

    • Velmi běžná přizpůsobení by měla být vystavena jako vlastnosti ovládacího prvku a spotřebované šablonou.

    • Méně časté (i když ne vzácné) přizpůsobení by mělo být vystaveno jako připojené vlastnosti a spotřebované šablonou.

    • Je přijatelné, aby známá, ale vzácná přizpůsobení vyžadovala nové šablonování.

Úvahy o motivu

  • styly motivů by se měly pokoušet mít konzistentní sémantiku vlastností napříč všemi motivy, ale nemají žádnou záruku. V rámci jeho dokumentace by měl mít váš ovládací prvek dokument popisující sémantiku vlastností ovládacího prvku, tedy "význam" vlastnosti ovládacího prvku. Například ovládací prvek ComboBox by měl definovat význam vlastnosti Background v rámci ComboBox. Výchozí styly ovládacího prvku by se měly pokusit dodržovat sémantiku definovanou v dokumentu napříč všemi motivy. Ovládací uživatelé by si na druhou stranu měli být vědomi toho, že se sémantika vlastností může změnit z tématu na téma. V některých případech nemusí být daná vlastnost v rámci vizuálních omezení vyžadovaných konkrétním motivem vyjádřitelná. (Například klasický motiv nemá jediné ohraničení, na které lze použít Thickness pro mnoho ovládacích prvků.)

  • Styly motivů nemusí mít konzistentní sémantiku spouštěčů ve všech motivech. Chování vystavené stylem ovládacího prvku prostřednictvím triggerů nebo animací se může lišit od motivu po motiv. Uživatelé ovládacích prvků by měli vědět, že ovládací prvek nemusí nutně používat stejný mechanismus k dosažení určitého chování napříč všemi motivy. Jeden motiv může například použít animaci k vyjádření reakcí při přejetí myší, zatímco jiný motiv používá spouštěč. Může vést k nekonzistencím v zachování chování na přizpůsobených ovládacích prvcích. (Změna vlastnosti pozadí, například nemusí mít vliv na stav najetí ovládacího prvku, pokud je tento stav vyjádřen pomocí triggeru. Pokud se ale stav přechodu myší implementuje pomocí animace, změna na pozadí by mohla nenávratně přerušit animaci, a proto přechod stavu.)

  • styly motivů nemusí mít konzistentní sémantiku rozložení ve všech motivech. Výchozí styl například nemusí zaručit, že ovládací prvek bude zabírat stejnou velikost ve všech motivech nebo zaručit, že ovládací prvek bude mít stejné okraje obsahu / odsazení napříč všemi motivy.

Viz také