poniedziałek, 28 listopada 2011

WPF - Resources

Właściwość Resources jest zdefiniowana w klasie FrameworkElement i jest dostępna we wszystkich klasach jej pochodnych. Właściwość ta zawiera dostępne dla danego widoku zasoby. Property Resources jest typu ResourceDictionary i możemy tam wrzucić dowolny obiekt dostępny w .NET. ResourceDictionary jest to słownik gdzie kluczem jest string lub typ, natomiast wartością może być dowolny obiekt. W xamlu Resources definiujemy w następujący sposób:
<Window.Resources>
<System:String x:Key="hulk">meHulk</System:String>
<Style TargetType="Button"/>
<Style TargetType="{x:Type ListBox}"/>
</Window.Resources>

W przypadku gdy kluczem jest typ możemy go zdefiniować na dwa sposoby ( z użyciem x:Type lub z jego pominięciem) tak jak widać w przykładzie powyżej. W Resources z reguły zamieszczamy wszelkiego rodzaju konwertery, templaty, style lub obiekty potrzebne nam w danym widoku. Można również stworzyć sobie osobny plik xaml typu ResourceDictionary, który nie ma żadnego code behind i wygląda mniej więcej tak:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!--Content-->
</ResourceDictionary>

Robi się to w celu uporządkowania kodu i zrobienia go bardziej przejrzystym. W przypadku dużego widoku, który posiada wiele zasobów jest to nieocenione. Jak widać w powyższym przykładzie użyte zostały znaczniki ResourceDictionary, których nie używaliśmy wcześniej, jednak oczywiście poprzedni przykład jest tożsamy z poniższym:
<Window.Resources>
<ResourceDictionary>
<System:String x:Key="hulk">meHulk</System:String>
<Style TargetType="Button"/>
<Style TargetType="{x:Type ListBox}"/>
</ResourceDictionary>
</Window.Resources>

Użycie znaczników ResourceDictionary jest jednak niezbędne tylko wtedy, gdy korzystamy z jakiejś właściwości klasy ResourceDictionary takiej jak np. MergedDictionaries
<Window.Resources>
<ResourceDictionary>
<System:String x:Key="hulk">meHulk</System:String>
</ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary1.xaml"/>
<ResourceDictionary Source="Dictionary2.xaml"/>
</ResourceDictionary.MergedDictionaries>
</Window.Resources>

Właściwość MergedDictionaries dołącza wszystkie oddzielnie zdefiniowane ResourceDictionary do danego widoku. W powyższym przykładzie użytkownik będzie miał swobodny dostęp do wszystkich zasobów zdefiniowanych w słownikach Dictionary1.xaml oraz Dictionary2.xaml. Co więcej z poziomu danej kontrolki mamy dostęp do wszystkich Resources kolejnych obiektów Parent, czyli wszystkich kontrolek znajdujących się wyżej w drzewie wizualnym.
Do obiektów znajdujących się w Resources możemy odwoływać się za pomocą dwóch markup extension: StaticResource i DynamicResource. W przypadku pierwszego mechanizm resourców wczytuje dany obiekt tylko raz, natomist w przypadku DynamicResource obiekt wczytywany jest od nowa przy każdym odwołaniu przez co jeżeli jest zmodyfikowany zmiany będą widoczne. Mówiąc bardziej dokładnie StaticResource jest ustalany w czasie kompilacji, natomiast DynamicResource jest ustalany w czasie działania programu. Zasadniczo StaticResource powinniśmy używać w większości przypadków. Użycie DynamicResource zużywa więcej czasu procesora jednak może przyspieszyć samo uruchamianie się programu. Poza tym może się przydać w przypadku gdy potrzebujemy w czasie działania programu podmienić zasoby (np podmienić skórkę programu).

Warto wspomnieć, o atrybucie Shared typu Boolean. Jeżeli ustawimy go na false, wówczas dla każdego żądania o dany obiekt, będzie zwrócona osobna instancja. Przykładowo:
...Resources>
<Converters:Converter x:Key="Konwerter" x:Shared="False"/>
</...Resources>

Każda kontrolka, która korzysta z “Konwerter” uzyska oddzielną instancję klasy Converter. Domyślnie wszystkie kontrolki współdzielą ze sobą jedną instancję.
Poza tym warto pamiętać, że Resource można “nadpisywać”. Jeżeli w domyślnym stylu ListBox’a użyty jest kolor systemowy HighlightBrushKey wówczas zaznaczenie przez użytkownika dowolnego Item podświetla go na niebiesko. Możemy zmienić ten kolor definiując color o takim samym kluczu:
<ListBox.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent" />
</ListBox.Resources>

Taki wpis zapewni, że nie będziemy mieli podświetlenia domyślnego w naszym ListBox’ie.

1 komentarze:

Anonimowy pisze...

Świetne materiały. Krótko i na temat. Gratuluje

Prześlij komentarz

 
Design by Free WordPress Themes | Bloggerized by Lasantha - Premium Blogger Themes | Online Project management