Style

Style jest to mechanizm wprowadzony w WPF-ie, a następnie w Silverlighcie, dzięki któremu w łatwy sposób można ujednolicić wygląd elementów naszej aplikacji.
Style z reguły definiowane są w zasobach. Mogą to być zarówno zasoby całej aplikacji, danego okna lub nawet wybranej kontrolki.
Przykładowy styl może wyglądać w następujący sposób:

Każdy styl jest rozpoznawany dzięki unikalnemu kluczowi – parametr x:Key. Możliwe jest pominięcie klucza, w przypadku gdy ustawiona zostanie właściwść TargetType. Jednakże zdefiniowanie właściwości TargetType spowoduje, że dany styl będzie automatycznie zastosowany do wszystkich kontrolek danego typu. W przypadku gdybyśmy jednak chcieli wyłączyć dany styl dla pojedynczej kontrolki możemy zawsze przypisać mu wartość x:Null
Jak widać styl posiada kolekcję obiektów typu Setter. Najważniejszymi propertisami każdego Settera są:

  • Property – określa nazwę właściwości, którą dany styl będzie modyfikować,
  • Value – określa wartość właściwości określonej w elemencie Property

Dla przykłady – następujący styl:

ustawi rozmiar czcionki na buttonie na 22 pkt. Jako, że nie została ustawiona właściwość TargetType dla stylu, musimy podawać pełną nazwę właściwości(czyli nazwę klasy oraz nazwę właściwości).
Oczywiście możemy również ustawiać bardziej skomplikowane właściwości

W przypadku gdybyśmy pisali w Silverlighcie właściwość TargetType ustawia się troszeczkę inaczej. Mianowicie zamiast
TargetType{x:Type Button} piszemy TargetType{Button}

Właściwość TargetType określa nam dla jakiego typu obiektów(kontrolek) dany typ jest przeznaczony. Styl z pierwszego przykładu można zapisać następująco:

Dzięki użyciu właściwości TargetType, kompilator wie, że dany styl jest przeznaczony dla Buttona, dlatego też możemy w Setterze użyć skróconej nazwy właściwości(FontSize zamiast Button.FontSize). Ponadto dzięki użyciu TargetType, możemy pominąć definiowanie klucza po jakim nasz styl będzie rozpoznawany. Od tej chwili wszystkie buttony będą renderowane z użyciem powyższego stylu (oczywiście jeżeli styl ten będzie w resourcach danej kontrolki).

Dziedziczenie styli

Style mogą być dziedziczone. Oznacza to tyle, że styl pochodny będzie rozszerzał styl bazowy. W przypadku gdy styl bazowy ma zdefiniowany TargetType, styl dziedziczący nie może go zmienić. W celu zdefiniowania dziedziczenia używa się właściwości BasedOn. Przykładowe dziedziczenie styli pokazano poniżej

W stylu dziedziczącym można przesłaniać właściwości ze stylu bazowego. W przypadku gdy nie zostaną one przesłonięte, użyte zostaną propertisy ze stylu bazowego.
W celu zaaplikowania stylu do jakiejś kontrolki posługujemy się następującą składnią

myStyle – klucz stylu zdefiniowanego w zasobach.

Style

Commands – czyli interakcja widoku z ViewModelem cz.2

Tak jak wspomniałem w poprzednim wpisie, tym razem zajmiemy się tworzeniem własnej klasy implantującej interfejs ICommand .

1. Implementacja interfejsu ICommand – WPF

Klasa implementująca ICommand może wyglądać w następujący sposób

Klasa DelegateCommand przyjmuje w konstruktorze dwa parametry – delegaty do funkcji. Pierwszy z nich jest to delegat do funkcji, która ma się wykonać, gdy komenda może zostać wykonana.Drugi natomiast jest to delegat do funkcji, która sprawdza czy dana komenda może zostać wykonana.Ważnym elementem jest tutaj następujący kawałek kodu :

który podłącza naszą klasę do WPF-owego systemu komend.
Teraz wystarczy w ViewModelu stworzyć obiekt typu DelegateCommand przekazać do niego odpowiednie funkcje, a następnie zbindować go do widoku. Może to wyglądać w następujący sposób:

  • ViewModel
  • Widok (XAML)

2. Implementacja interfejsu ICommand Silverlight

Przedstawiony powyżej przykład skompiluje się jedynie w aplikacji WPF-owej. Silverlight niestety nie posiada CommandManagera, dlatego też gdy chcemy używać komend właśnie w tej technologii musimy zmodyfikować nasz kod na następujący:

Jak widać w funkcji

sami musimy zadbać o wywołanie zdarzenia

Ponadto dopisana została funkcja

funkcję tą musimy wywoływać zawsze gdy zmieni się jakaś właściwość, która ma mieć wpływ na stan przycisku zbindowanego do naszej komendy.

3. Przykład

Załóżmy,że na widoku mamy przycisk edytuj, który powinien być aktywny tylko i wyłącznie wtedy, gdy zaznaczono jakiś element na gridzie. Przycisk ten jest zbindowany do komendy EditCommand. Jak już wcześniej wspomniano, z powodu braku w Silverlighcie CommandManagera sami musimy wywołać zdarzenie informujące o potrzebie zmiany stanu przycisku. Dlatego też, w ViewModelu została stworzona właściwość SelectedItem

która reaguje na zmiany zaznaczenia na gridzie. W chwili, gdy zaznaczenie się zmienia, wywoływany jest seter z tej właściwości, w którym to wywołujemy funkcję EditCommand.RaiseCanExecute(). Dzięki czemu informujemy kontrolkę o ewentualnej potrzebie zmiany jej stanu.

4. Podsumowanie

Komendy w bardzo prosty i wygodny sposób pozwalają nam wywoływać metody bezpośrednio z ViewModelu. Niestety mają one również swoje ograniczenia:

  • reagują jedynie na zdarzenie Click,
  • można je wykorzystać jedynie na kontrolkach dziedziczących po klasie ButtonBase oraz kontrolkach typu MenuItem
Commands – czyli interakcja widoku z ViewModelem cz.2