WPF / MVVM Zwischen verschiedenen Views Wechseln

LosLegator

Grünschnabel
Hallo,

ich fang grad an mich ein Wenig mit WPF zu beschäftigen und stehe nun grad vor einem Problem.

Ich habe mein MainWindow Gebastelt mit einer Menüleiste und einer Pane auf dem der Content angezeigt werden soll.

Nun will ich wenn dich verschiedene MenüPunkte Klicke immer andere Views angezeigt bekommen.
Wie mache ich das genau ?

Code:
<Window x:Class="MyApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:dg="http://schemas.microsoft.com/wpf/2008/toolkit"
        xmlns:vm="clr-namespace:MyApp.ViewModels"
        xmlns:vw="clr-namespace:MyApp.Views"
        Title="MyApp v.1.01b"
	    Width="825" Height="700"
	    MinWidth="825" MinHeight="700" 
        ResizeMode="CanResizeWithGrip">
    <DockPanel x:Name="LayoutRoot">    
        <!--Menü-->
        <Menu DockPanel.Dock="Top" x:Name="menu" Height="25">
            <MenuItem x:Name="miOption" Header="Option">
                <MenuItem x:Name="miExit" Header="Exit" Command="{Binding ExitCommand}" />
            </MenuItem>
            <MenuItem Header="Option 1">
                <MenuItem Header="Mache Dies" Command="{Binding Show1Command}"/>
                <MenuItem Header="Mach Das" Command="{Binding Show2Command}" />
            </MenuItem>
        </Menu>
       
        <!--ContentPanel-->
        <StackPanel x:Name="content">
         
                Hier sollen meine Views rein.

        </StackPanel>
    </DockPanel>
</Window>

Ich habe dann mir 2 Views gebaut.

Des weiteren habe ich in der Datei MainWindowViewModel.cs die Methoden

Code:
private RelayCommand m_Show1Command;

        public ICommand Show1Command
        {
            get
            {
                if (m_Show1Command == null)
                {
                    m_Show1Command = new RelayCommand(param => CanShow1(), param => Show1());
                }

                return m_Show1Command;
            }
        }

        private static bool CanShow1()
        {
            return true;
        }

        private void GaShow1()
        {
            MessageBox.Show("Hier.");

           Was muss hier gemacht werden.

        }

Auf den Menüaufruf reagiert das System und es wird eine MSG-Box angezeigt. Aber was muss ich tun, damit mein neuer View als Datacontext in meinem Stackpanel angezeigt wird?

Ich hoffe ihr könnt mir helfen.

MFG Legator
 
Zuletzt bearbeitet:
Ich bin selber gerade erst dabei MVVM zu lernen, da aber sonst niemand geantwortet hat, schreibe ich mal was mir dazu einfällt.

Du willst zwischen zwei Views hin- und herwechseln? Sollen die das selbe ViewModel haben oder ein anderes?

Was ist die GaShow1-Methode?

Dein ViewModel sollte so geartet sein, dass es ohne irgend eine View leben könnte.
Das verstehe ich so, dass die View selber Platz für eine andere View machen muss, ohne dass das ViewModel verwendet wird. Ich weiß aber nicht ob ich das richtig verstanden habe.
Google hat mir da das hier geliefert: Binding Multiple Views to the Same ViewModel. Da ist die Rede von TemplateSelectoren (weiß (noch) nicht was das ist).

Noch was, was nicht zur Fragestellung gehört:
Aber was muss ich tun, damit mein neuer View als Datacontext in meinem Stackpanel angezeigt wird?
Da steckt ein sprachlicher Fehler drin. Die View wird nicht als DataContext angezeigt, sondern das ViewModel soll der DataContext der View sein.

Ich glaube, der Name der Klasse "MainWindowViewModel" ist falsch herum gewählt. Besser wäre "DatenViewModel". Denn das ViewModel interessiert sich nicht dafür, wie die View-Klasse heißt (oder was die Klasse sonst so kann), da es mit der View-Klasse nur über DataBinding kommuniziert. Vielmehr muss das ViewModel wissen, wie die Model-Klasse ausschaut. Daher würde ich eine ViewModel-Klasse nach der Model-Klasse benennen. Und wenn meine Model-Klasse "Daten" heißt, dann also "DatenViewModel".
 
Zuletzt bearbeitet:
1. Deine Views und deren ViewModels erben alle von ViewModelBase (gleicher Typ)
2. In deiner MainWindow.xaml hast du ein ContentControl.

<ContentControl Content="{Binding VM}"/>

3. VM is eine Property in deinem MainViewModel:

public ViewModelBase VM
{
get { return _vm; }
set
{
if (_vm != value)
{
_vm = value;
this.RaisePropertyChanged("VM");
}
}
}

Da alle "ViewModels" die geswitcht werden den gleichen Typ haben (siehe oben) ist die Property vom Typ ViewModelBase.

Nehmen wir an du hast 2 Buttons in deiner MainWindow.xaml.


<Button Command="{Binding ShowView1Command}" />
<Button Command="{Binding ShowView2Command}" />

In deinem MainViewModel passiert dann das:

private RelayCommand _showView1Command;
public RelayCommand ShowView1Command
{
get { return _showView1Command **** (_showView1Command = new RelayCommand( InitDailyView) ); }
}

private RelayCommand _showView2Command;
public RelayCommand ShowView2Command
{
get { return _showView2Command **** (_showView2Command = new RelayCommand( InitWeeklyView ) ); }
}


private void InitView1()
{
VM = new ViewModel1();
}

private void InitView2()
{
VM = new ViewModel2();
}

Wenn das ViewModel1 objekt jetzt vom MainViewModel runterkommt via Binding zum ContentControl, stellst sich die frage welche View möchtest du für welches ViewModel anzeigen bzw. datatemplaten. Daher mach noch das:

xmlns:ViewModel="clr-namespace:XXX.ViewModel"
xmlns:View....
<Window.Resources>

<DataTemplate DataType="{x:Type ViewModel:ViewModel1}">
<View:ViewModel1View/>
</DataTemplate>

// Das gleiche mit ViewModel2 machen...

</Window.Resources>

Das wars, deine Views switchen nun. Ersetze die 4 "****" durch "****" ****-operator in c# musst googeln.

Je nach MVVM framework ersetzt du RelayCommand durch ICommand/DelegateCommand etc...
 
Zuletzt bearbeitet:
Zurück