WPF i MEF – sterowanie wyglądem aplikacji w zależności od posiadanych zasobów.

Jednym z fundamentów WPF’a są zasoby – Resources. Definiowane w ResourceDictionary czyli słowniku zasobów. Każdy element słownika posiada swój klucz, który używamy do pobrania zasobu „z bazy”.

Odwołanie do zasobu może odbyć się na dwa sposoby.

  • StaticResource – Wartość jest ustalona podczas załadowania XAML.
  • DynamicResource – Wartość jest ustalona w momencie, kiedy obiekt ma się pojawić.

To zachowanie DynamicResource możemy wykorzystać do wprowadzenia ciekawych rozwiązań.

Jeżeli DynamicResource odwołuje się do zasobu aplikacji, to może być on przykryty przez inny zasób o tej samej nazwie.

Jeżeli mamy kilku klientów, a każdy z nich chce innych kolorów w swojej aplikacji, możemy załatwić tą prośbę dołączając do binarek .dll z zasobami, które zmienią kolory w odpowiednich miejscach.

Przykładowa aplikacja ma na celu wyświetlać dwukolorową flagę.

polish_flag

Aplikacja zawiera swoje zasoby zdefiniowane w osobnej .DLL o nazwach MainResources (podstawowe zasoby aplikacji), ClientResources (zasoby zmienione na danego klienta).

MainResources

Ten ResourceDictionary zawiera coś, co nie każdy ResourceDictionary posiada. Tym czymś jest klasa z code-behind.

Klasa służy do wprowadzenia atrybutów z frameworka MEF. Dzięki, któremu w łatwy sposób zaimportujemy słowniki zasobów do naszej aplikacji.

  • Atrybut [Export(typeof(ResourceDictionary))]upublicznia dla MEFa tą klasę.
  • Atrybut [ExportMetadata("Order", 100)] – to dodatkowe informacje o tej klasie, Order wykorzystamy do posortowania naszych danych. Im coś ma większy Order to zostanie później wczytane do globalnego słownika zasobów, a to co później jest wczytywane to ma ważniejszą pozycję. To co zostanie wczytane jako ostatnie przykryje to co zostało wczytane wcześniej.

Client Resources

Słownik posiada zdefiniowane dwa klucze, które mają przykryć te z MainResources.

Prawodopodobnie będziesz chciał pogmerać w .csproj. Aby ustawić zależności kompilacji pliku AllStyles.xaml.cs nad AllStyles.xaml. By to zrobić musisz w pliku .csproj znaleźć linijkę: <Compile Include="AllStyles.xaml.cs"> i zastąpić ją:

Dzięki czemu w widoku projektu pojawi się nam „graficzna reprezentacja zależności”.

depend_upon

Widok Aplikacji

Ładowanie wielu ResourceDictionary

Założenie jest takie, że assembly z zasobami są umieszczone w katalogu Resources.

Potem dzięki słowniki, są sortowane przez wartość Order i ładowane do głównego słownika aplikacji Application.Current.Resources.

Pierwszy screenshot pokazał jak aplikacja wygląda jak w katalogu Resources znajduje się tylko MainResources.dll, poniżej znajduje się przykład w którym w katalogu Resources są oba pliki MainResources.dll i ClientResources.dll.

ukraine_flag

Podsumowanie

Dzisiaj mogłeś się dowiedzieć:

  • Można dodać klasę code-behind dla ResourceDictionary
  • Możesz wykorzystać framework MEF do ładowania zasobów do aplikacji. W zależności czy są (czy nie) biblioteki z zasobami możesz zmieniać wygląd aplikacji.

Pełen kod