Wytyczne do projektowania kontrolek w określonych stylach

W tym dokumencie przedstawiono podsumowanie zestawu najlepszych rozwiązań, które należy wziąć pod uwagę podczas projektowania kontrolki, którą zamierzasz łatwo stylizować i konfigurować do tworzenia szablonów. Doszliśmy do tego zestawu najlepszych rozwiązań przez wiele prób i błędów podczas pracy nad stylami kontrolek motywu dla wbudowanego zestawu kontrolek WPF. Dowiedzieliśmy się, że udany styl jest tak samo funkcją dobrze zaprojektowanego modelu obiektów, jak sam styl. Grupa odbiorców przeznaczona dla tego dokumentu jest autorem kontrolki, a nie autorem stylu.

Terminologia

"Styling and templating" odnosi się do zestawu technologii, które umożliwiają autorowi kontrolki odroczenie wizualnych aspektów kontrolki do stylu i szablonu kontrolki. Ten pakiet technologii obejmuje:

  • Style (w tym zestawy właściwości, wyzwalacze i scenorysy).

  • Zasoby.

  • Szablony kontrolek.

  • Szablony danych.

Aby zapoznać się z wprowadzeniem do stylów i tworzenia szablonów, zobacz Styling and Templating (Styleing and Templating).

Przed rozpoczęciem: zrozumienie kontrolki

Zanim przejdziesz do tych wytycznych, ważne jest, aby zrozumieć i zdefiniować wspólne użycie kontrolki. Styl ujawnia często niesforny zestaw możliwości. Kontrolki napisane do szerokiego użycia (w wielu aplikacjach, przez wielu deweloperów) stają przed wyzwaniem, którego można użyć do wprowadzania dalekosiężnych zmian w wyglądzie wizualizacji kontrolki. W rzeczywistości stylizowany formant może nawet nie przypominać intencji autora kontrolki. Ponieważ elastyczność oferowana przez styl jest zasadniczo nieograniczona, możesz użyć pomysłu wspólnego użycia, aby ułatwić określanie zakresu decyzji.

Aby zrozumieć typowe użycie kontrolki, warto zastanowić się nad propozycją wartości kontrolki. Jaka kontrolka przynosi do tabeli, że żadna inna kontrolka nie może zaoferować? Typowe użycie nie oznacza żadnego konkretnego wyglądu wizualnego, ale raczej filozofię kontroli i rozsądny zestaw oczekiwań dotyczących jego użycia. Dzięki temu można założyć pewne założenia dotyczące modelu kompozycji i zachowań zdefiniowanych w stylu kontrolki w typowym przypadku. Na przykład w przypadku ComboBoxprogramu zrozumienie typowego użycia nie daje żadnych szczegółowych informacji na temat tego, czy dany ComboBox element ma zaokrąglone rogi, ale daje wgląd w fakt, że ComboBox prawdopodobnie potrzebuje okna podręcznego i jakiegoś sposobu przełączania się, czy jest otwarty.

Ogólne wskazówki

  • Nie wymuszaj ściśle kontraktów szablonów. Kontrakt szablonu kontrolki może składać się z elementów, poleceń, powiązań, wyzwalaczy, a nawet ustawień właściwości, które są wymagane lub oczekiwane, aby kontrolka działała prawidłowo.

    • Zminimalizuj kontrakty tak bardzo, jak to możliwe.

    • Projektuj zgodnie z oczekiwaniami, że w czasie projektowania (czyli w przypadku korzystania z narzędzia projektowego) często szablon kontrolki ma być w stanie niekompletnym. WPF nie oferuje "komponowania" infrastruktury stanowej, więc kontrole muszą być zbudowane z oczekiwaniami, że taki stan może być ważny.

    • Nie zgłaszaj wyjątków, gdy nie następuje żaden aspekt kontraktu szablonu. W tych wierszach panele nie powinny zgłaszać wyjątków, jeśli mają zbyt wiele lub zbyt mało dzieci.

  • Uwzględnianie funkcji peryferyjnych w elementach pomocnika szablonu. Każda kontrolka powinna być skoncentrowana na jej podstawowych funkcjach i prawdziwej wartości i zdefiniowaniu przez wspólne użycie kontrolki. W tym celu użyj elementów kompozycji i pomocnika w szablonie, aby umożliwić zachowanie i wizualizacje peryferyjne, czyli te zachowania i wizualizacje, które nie przyczyniają się do podstawowych funkcji kontrolki. Elementy pomocnika dzielą się na trzy kategorie:

    • Autonomiczne typy pomocników to publiczne i wielokrotnego użytku kontrolki lub elementy pierwotne, które są używane "anonimowo" w szablonie, co oznacza, że ani element pomocnika, ani kontrolka stylizowanego nie są świadomi innej. Technicznie każdy element może być typem anonimowym, ale w tym kontekście termin opisuje te typy, które hermetyzują wyspecjalizowane funkcje w celu włączenia scenariuszy docelowych.

    • Elementy pomocnicze oparte na typach to nowe typy, które hermetyzują wyspecjalizowane funkcje. Te elementy są zwykle projektowane z węższym zakresem funkcjonalności niż typowe kontrolki lub elementy pierwotne. W przeciwieństwie do autonomicznych elementów pomocnika, elementy pomocnicze oparte na typach są świadome kontekstu, w którym są używane i zazwyczaj muszą udostępniać dane kontrolce, do której należą.

    • Nazwane elementy pomocnicze są typowymi kontrolkami lub elementami pierwotnymi, których kontrolka oczekuje odnaleźć w szablonie według nazwy. Te elementy mają dobrze znaną nazwę w szablonie, umożliwiając kontrolce znalezienie elementu i interakcję z nim programowo. W dowolnym szablonie może istnieć tylko jeden element o podanej nazwie.

    W poniższej tabeli przedstawiono obecnie elementy pomocnicze stosowane przez style kontrolek (ta lista nie jest wyczerpująca):

    Element Type Używana przez
    ContentPresenter Oparte na typach Button, , CheckBoxRadioButton, Framei tak dalej (wszystkie ContentControl typy)
    ItemsPresenter Oparte na typach ListBox, ComboBox, Menui tak dalej (wszystkie ItemsControl typy)
    ToolBarOverflowPanel O nazwie ToolBar
    Popup Autonomiczne ComboBox, ToolBar, Menu, ToolTipi tak dalej
    RepeatButton O nazwie Slider, ScrollBari tak dalej
    ScrollBar O nazwie ScrollViewer
    ScrollViewer Autonomiczne ListBox, ComboBox, Menu, Framei tak dalej
    TabPanel Autonomiczne TabControl
    TextBox O nazwie ComboBox
    TickBar Oparte na typach Slider
  • Zminimalizuj wymagane powiązania określone przez użytkownika lub ustawienia właściwości dla elementów pomocnika. Często element pomocnika wymaga pewnych powiązań lub ustawień właściwości w celu prawidłowego działania w szablonie kontrolki. Element pomocnika i kontrolka szablonu powinny, jak najwięcej, ustanowić te ustawienia. Podczas ustawiania właściwości lub ustanawiania powiązań należy zachować ostrożność, aby nie przesłaniać wartości ustawionych przez użytkownika. Oto konkretne najlepsze rozwiązania:

    • Nazwane elementy pomocnicze powinny być identyfikowane przez element nadrzędny, a element nadrzędny powinien ustanowić wszystkie wymagane ustawienia w elemecie pomocnika.

    • Elementy pomocnika oparte na typach powinny określać wszystkie wymagane ustawienia bezpośrednio na siebie. Może to wymagać, aby element pomocnika wysyłał zapytania o kontekst informacji, w którym jest używany, w tym TemplatedParent jego (typ kontrolki szablonu, w którym jest używany). Na przykład automatycznie wiąże Content właściwość jej TemplatedParent z właściwościąContent, gdy jest używana w typie pochodnymContentControl. ContentPresenter

    • Autonomicznych elementów pomocnika nie można zoptymalizować w ten sposób, ponieważ z definicji ani element pomocnika, ani element nadrzędny nie wie o drugiej.

  • Użyj właściwości Name, aby flagować elementy w szablonie. Kontrolka, która musi znaleźć element w swoim stylu, aby uzyskać do niego dostęp programowo, powinna to zrobić przy użyciu Name właściwości i paradygmatu FindName . Kontrolka nie powinna zgłaszać wyjątku, gdy element nie zostanie znaleziony, ale dyskretnie i bezpiecznie wyłącz funkcjonalność, która wymagała tego elementu.

  • Najlepsze rozwiązania dotyczące wyrażania stanu kontroli i zachowania w stylu. Poniżej znajduje się uporządkowana lista najlepszych rozwiązań dotyczących wyrażania zmian stanu kontroli i zachowania w stylu. Należy użyć pierwszego elementu na liście, który umożliwia korzystanie ze scenariusza.

    1. Powiązanie właściwości. Przykład: powiązanie między ComboBox.IsDropDownOpen i ToggleButton.IsChecked.

    2. Wyzwolone zmiany właściwości lub animacje właściwości. Przykład: stan aktywowania obiektu Button.

    3. Command. Przykład: LineUpCommand / LineDownCommand w pliku ScrollBar.

    4. Autonomiczne elementy pomocnicze. Przykład: TabPanel w pliku TabControl.

    5. Typy pomocnika oparte na typach. Przykład: ContentPresenter w pliku w Buttonpliku TickBarSlider.

    6. Nazwane elementy pomocnika. Przykład: TextBox w pliku ComboBox.

    7. Zdarzenia bąbelkowe z nazwanych typów pomocników. W przypadku nasłuchiwania zdarzeń bąbelkowych z elementu stylu należy wymagać, aby element generujący zdarzenie mógł zostać jednoznacznie zidentyfikowany. Przykład: Thumb w pliku ToolBar.

    8. Zachowanie niestandardowe OnRender . Przykład: ButtonChrome w pliku Button.

  • Używaj wyzwalaczy stylów (w przeciwieństwie do wyzwalaczy szablonu) oszczędnie. Wyzwalacze wpływające na właściwości elementów w szablonie muszą być zadeklarowane w szablonie. Wyzwalacze wpływające na właściwości kontrolki (nie TargetName) mogą być zadeklarowane w stylu, chyba że wiesz, że zmiana szablonu również powinna zniszczyć wyzwalacz.

  • Zachowaj spójność z istniejącymi wzorami stylów. Wiele razy istnieje wiele sposobów rozwiązania problemu. Należy pamiętać o istniejących wzorach stylów kontrolek i, jeśli to możliwe. Jest to szczególnie ważne w przypadku kontrolek, które pochodzą z tego samego typu podstawowego (na przykład ContentControl, , ItemsControli RangeBasetak dalej).

  • Uwidacznianie właściwości w celu włączenia typowych scenariuszy dostosowywania bez ponownego tworzenia. WPF nie obsługuje podłączonych/dostosowywalnych części, więc użytkownik kontrolki pozostaje z tylko dwiema metodami dostosowywania: ustawianie właściwości bezpośrednio lub ustawianie właściwości przy użyciu stylów. Mając to na uwadze, należy uwidocznieć ograniczoną liczbę właściwości przeznaczonych dla bardzo typowych scenariuszy dostosowywania o wysokim priorytecie, które w przeciwnym razie wymagają ponownego wdrażania. Poniżej przedstawiono najlepsze rozwiązania dotyczące tego, kiedy i jak włączyć scenariusze dostosowywania:

    • Bardzo typowe dostosowania powinny być uwidocznione jako właściwości kontrolki i używane przez szablon.

    • Mniej typowe (choć nie rzadkie) dostosowania powinny być uwidocznione jako dołączone właściwości i używane przez szablon.

    • Jest to dopuszczalne dla znanych, ale rzadkich dostosowań, aby wymagać ponownego tworzenia.

Zagadnienia dotyczące motywu

  • Style motywu powinny próbować mieć spójną semantyka właściwości we wszystkich motywach, ale nie gwarantuje. W ramach dokumentacji kontrolka powinna zawierać dokument opisujący semantyka właściwości kontrolki, czyli "znaczenie" właściwości dla kontrolki. Na przykład kontrolka ComboBox powinna definiować znaczenie Background właściwości w obiekcie ComboBox. Domyślne style kontrolki powinny podjąć próbę wykonania semantyki zdefiniowanej w tym dokumencie we wszystkich motywach. Z drugiej strony należy pamiętać, że semantyka właściwości może ulec zmianie z motywu na motyw. W niektórych przypadkach dana właściwość może nie być wyrażalna w ramach ograniczeń wizualnych wymaganych przez określony motyw. (Motyw klasyczny, na przykład, nie ma pojedynczego obramowania, do którego Thickness można zastosować wiele kontrolek).

  • Style motywu nie muszą mieć spójnych semantyki wyzwalaczy we wszystkich motywach. Zachowanie uwidocznione przez styl kontrolki za pośrednictwem wyzwalaczy lub animacji może się różnić w zależności od motywu. Użytkownicy kontroli powinni mieć świadomość, że kontrolka nie musi używać tego samego mechanizmu, aby osiągnąć określone zachowanie we wszystkich motywach. Na przykład jeden z motywów może używać animacji do wyrażania zachowania aktywowania wskaźnika myszy, w którym inny motyw używa wyzwalacza. Może to spowodować niespójności w zachowaniu zachowania w dostosowanych kontrolkach. (Zmiana właściwości tła może na przykład nie mieć wpływu na stan aktywowania kontrolki, jeśli ten stan jest wyrażony przy użyciu wyzwalacza. Jeśli jednak stan aktywowania jest implementowany przy użyciu animacji, zmiana na tło może nieodwracalnie przerwać animację i w związku z tym przejście stanu.

  • Style motywu nie muszą mieć spójnych semantyki "układu" we wszystkich motywach. Na przykład styl domyślny nie musi zagwarantować, że kontrolka będzie zajmować taką samą ilość rozmiaru we wszystkich motywach lub zagwarantować, że kontrolka będzie miała te same marginesy zawartości/dopełnienie we wszystkich motywach.

Zobacz też