C# WPF Inhalt Wechseln MVVM?
Hallo,
ich bin noch relativ neu in der Welt von C# WPF.
Meine frage ist:
Wie kann ich meinen Inhalt mit dem MVVM Muster wechseln ?
Also beim Klicken auf ein Button damit was anderes gezeigt wird.
Momentan habe ich es so das ich ein ICommand Klasse habe für die Buttons, ein ObservableObject (INotifyPropertyChanged) für die Benachrichtigungen.
Auf meiner MainView habe ich dann ein UserControl in meinem Grid:
<UserControl Content="{Binding CurrentView}"/>
In meiner VM Klasse:
private UserControl currentView;
public UserControl CurrentView
{
get { return currentView; }
set { currentView = value; OnPropertyChanged(); => Läuft mit NameOf }
}
Nun bin ich mir aber bewusst das ich gegen die MVVM Regel Verstöße weil ich das UserControl in meiner VM angelegt habe.
Gibt es außer dem UserControl noch andere Möglichkeiten den Content zu wechseln ?
Hab auch mal gelesen das zu viele UserControls die Anwendung langsamer macht, stimmt das ?
Um das Beispiel Komplett zu halten:
BeispielCommand = new RelayCommand(() =>
{
CurrentView = new NewView();
}, () => true);
Damit Wechsel ich den Content beim Drücken auf ein Button
3 Antworten
Guck dir mal Frames und Pages mit dem NavigationService an. Du hast praktisch einen übergeordneten Container, in dem du deine Pages anzeigst. In diesen kannst du dann mit dem NavigationService eine neue Page laden und auch vor und zurückgehen.
https://docs.microsoft.com/en-us/dotnet/api/system.windows.controls.frame?view=net-5.0
Ich würde die Objektmethode nehmen.
Ja, das funktioniert wunderbar. Und nein, das ist nicht nur fürs Web.
Ich habe nicht viel Ahnung von UserControl, von daher kann ich dir nicht sagen was „besser“ für deine Anwendung ist.
Aber wenn du einfach mehrere Seiten in deiner Anwendung haben möchtest, zwischen denen du mit nur einem Befehl im Code navigieren können möchtest, ist das eine gute Möglichkeit.
Das UserControl sollte man auch nicht als "normales" Control im XAML nutzen, das ist nur die Basis für eigene Controls. Und wo wir beim Thema sind: Schau dir Mal den Unterschied von UserControl und CustomControl an, der scheint gering, kann bei der Anwendung aber sehr wichtig werden.
Aber zum Thema:
Die einfachste Ausführung wäre, Du gibst in der CurrentView-Property nicht das UserControl direkt, sondern das ViewModel dafür zurück. In der View verwendest Du dann ein ContentControl und bindest CurrentView an die ContentProperty.
Um nun die View anzuzeigen gibt es drei Wege:
- Du definierst über dem ContentControl in Resourcen DataTemplates ohne Key (ganz wichtig) und der DataType-Property gibst Du den Typ des ViewModels. Das ContentControl findet dann automatisch das passenden DataTemplate
- Du implementierst einen DataTemplateSelector und weist diesen der ContentTemplateSelector-Property vom ContentControl zu. Der DataTemplateSelector bekommt dann das ViewModel und gibt das DataTemplate dafür zurück.
- Du weißt dem ContentControl direkt ein DataTemplate zu, das geht über die ContentTemplate-Property. So ginge dann aber nur eine View für alle ViewModels.
Das Ganze kann man jetzt ewig weit treiben. Normalerweise implementiert man dann eine Art NavigationService, der im Hintergrund eine Art NavigationManagementViewModel ändert, was sich den aktuellen Zustand der Navigation (zuletzt geöffneten Dialoge, modale Dialoge, aktuell geöffneter Dialog, etc.). Das eigentliche Window bekommt dann dieses ViewModel und zeigt auf die oben erklärte Weise alles an.
Die eigentlichen Dialoge können dann über diesen NavigationService navigieren, ohne dabei an andere Dialoge oder an das Management drum herum gekoppelt zu sein.
Es gibt aber auch fertig implementierte Varianten, zu navigieren, jedes Framework bietet da eigene Implementierungen für. Ich persönlich kann mich damit aber selten anfreunden. Z.B. zwingt mich die Variante von Xamarin in die UI, die mir vom jeweiligen Betriebssystem vorgegeben wird, weshalb ich wie oben beschrieben einen NavigationService gebaut, über den ich dann die volle Kontrolle habe.
PS:
Man könnte es auch noch ganz weit treiben und an einer zentralen Stelle eine Art Registry aufbauen, die ViewModel und View zueinander in Verbindung setzt. Das Ding kann dir dann anhand eines ViewModels die dazu passende View suchen.
Der Vorteil, wenn man das so macht, ist, dass man das dynamisch von außen verwalten kann, z.B. von einem Plugin-Management, was erst irgendwann später Plugins nachlädt.
Ein UserControl ist im Grunde auch nur geerbt von Steuerelementen also wenn ein UserControl nicht zu aufgeblasen ist macht das keinen Unterschied.
Laut MVVM sollte aber kein Steuerelement in der VM Vorhanden sein.
Wie kann ich das dann aber verwenden, ohne MVVM zu Verletzten ?
Ist das auch gut für Seitenwechseln innerhalb des WPF Programm ?
So wie ich das gelesen und Verstanden habe ist das für HTML/Web gedacht.
Suche aber nach einer MVVM Freundlichen Lösung Seiten Innerhalb des Programmes zu wechseln.