2009-05-25 18 views
6

Próbuję użyć podejścia MVVM-ish do mojego rozwoju WPF.Podstawy WPF: Współdzielone style globalne dla MVVM

Mam moje klasy widoku widoku logicznego w przestrzeni nazw ViewModel i mam pasujące styl dla tych klas modelu widok w obszarze nazw View.

Na razie mam moje informacje o widoku w plikach XAML ResourceDictionary, jak DataTemplates i Style, które są scalone w pojedynczą aplikację App.Resources ResourceDictionary w pliku app.xaml.

Jednak mam pewien rodzaj problemu z kurczakiem/jajkiem. Chcę, żeby były globalne style, których używam wszędzie. Na przykład chcę mieć własny niestandardowy styl tekstu o nazwie MonkeyText, który może być używany w różnych stylach w każdym miejscu. Nie mogę tego po prostu ustawić w pliku app.xaml, ponieważ pliki resourcedictionarys, które będą używać MonkeyText, są zawarte w tym pliku app.xaml.

Domyślam się, że to niemożliwe, alternatywnie byłoby użyć UserControls zamiast używać głównie DataTemplates do ustalenia moich widoków? Obawiam się, że użycie UserControls wiązałoby części VM i V zbyt blisko siebie.

Odpowiedz

10

WPF zapewnia DynamicResources właśnie z tego powodu. StaticResources - które najbardziej przypominają "tradycyjne" odniesienia w programowaniu - mają tylko problem, który napotkaliście; należy je zdefiniować i wczytać przed analizą stylu. Z drugiej strony DynamicResources nie muszą być definiowane przed punktem, w którym są używane - w rzeczywistości można je nawet tworzyć w locie. WPF dba o to, aby DynamicResources były automatycznie ładowane przez wszystkie style, które odwołują się do nich po ich załadowaniu.

Korzystanie z DynamicResources jest proste. Podczas tworzenia stylu MonkeyText, utwórz go tak jak zwykle:

<Style TargetType="TextBlock" x:Key="MonkeyText"> 
    <Setter Property="TextAlignment" Value="Center"/> 
    <!-- etc. --> 
</Style> 

A potem odwoływać się do niego z zewnątrz za pomocą DynamicResource:

<TextBlock Text="Hello, World!" Style="{DynamicResource MonkeyText}"/> 

Jeśli z jakiegokolwiek powodu, WPF nie może rozwiązać swój DynamicResource , to nie powiedzie się w trybie cichym bez żadnego wyjątku zgłoszonego (StaticResources generują wyjątki, gdy nie można ich rozwiązać). Zostanie jednak wydrukowany komunikat debugowania, gdy tak się stanie - więc miej oko na okno wyjściowe w Visual Studio.

Ponieważ DynamicResources współpracuje z zasobami, które są ładowane w dowolnym miejscu w dowolnej kolejności, możesz strukturować słowniki zasobów w dowolny sposób - więc umieszczając je w innych stylach widoku i łącząc je za pomocą jednej aplikacji. Źródła ResourceDictionary w app.xaml będzie działać poprawnie.

Więcej informacji o DynamicResources można znaleźć w dokumentach MSDN dla WPF.

+0

zawsze raczej się nad tym zastanawiałem, dzięki za odpowiedź, nigdy nie dotarłem wystarczająco daleko do WPF poza kilkoma apletami .. btw, w jaki sposób kaskady zależne viewmodels? czy masz tylko jeden "model widoku aplikacji" lub masz "model główny" z "childviewmodel" z "descendantviewmodel" – Firoso

+0

Zwykle masz jeden "główny" model widoku, a następnie twoje obiekty modelu są przez niego przywoływane i tworzą pewne hierarchia. To trochę bardziej skomplikowane - i zależy trochę od struktury danych w twojej aplikacji - ale to jest krótka wersja –

+0

Ale co by było, gdybyś chciał, aby MonkeyText był używany na wszystkich TextBlockach? W normalnym WPF możesz zadeklarować styl w App.xaml i dzięki TargetType będzie działać na wszystkich TextBlocks. Ale użycie MVVM nie działa, chyba że zadeklaruję DynamicResource na wszystkich kontrolkach. – Peter