Navigation mit WPF und Mvvm

Veröffentlicht von

Heute wollen wir uns eine einfache Navigation mit Mvvm und WPF anschauen. Diese erlaubt uns, rein mit ViewModellen und Data Binding, zwischen verschiedenen Seiten der UI zu navigieren.

Das Projekt gibt es am Ende des Projektes zum Download. Ziel ist die Navigation zwischen den einzelnen Seiten der UI ohne Code-Behind. Unsere UI ist einfach gestrickt:

Mit den Buttons auf der linken Seite können wir zwischen den Seiten der Anwendung wechseln. Die Anwendung besteht aus dem ViewModel für das Hauptfenster und 3 ViewModels für die einzelnen Seiten.

Die ViewModels für die Seiten sind von AViewModel abgeleitet, welches wiederum von ViewModelBase abgeleitet ist. Man sieht bereits, die Anwendung verwendet das MvvmLight Framework.

public class AViewModel : ViewModelBase
{
    private string _name = "";

    public string Name
    {
        get
        {
            return _name;
        }
        set
        {
            Set(() => Name, ref _name, value);
        }
    }
}

Die Eigenschaft “Name” verwenden wir für die Navigation über die Buttons und setzen wir im Konstruktor des jeweiligen ViewModels:

public View1ViewModel()
{
    Name = "View 1";
}

ViewModel des Hauptfensters

Schauen wir uns nun das ViewModel des Hauptfensters an:

public class MainViewModel : ViewModelBase
{
    private RelayCommand<AViewModel> _changePageCommand;
    private AViewModel _currentPageViewModel;

    private List<AViewModel> _viewModelList = new List<AViewModel>();

    public List<AViewModel> ViewModelList
    {
        get
        {
            return _viewModelList;
        }
    }

    public AViewModel CurrentPageViewModel
    {
        get
        {
            return _currentPageViewModel;
        }
        set
        {
            Set(() => CurrentPageViewModel, ref _currentPageViewModel, value);
        }
    }

    public RelayCommand<AViewModel> ChangePageCommand { get; private set; }   

    public MainViewModel()
    {
        ChangePageCommand = new RelayCommand<AViewModel>(p => ChangePageAction(p));

        _viewModelList.Add(ViewModelLocator.Instance.View1);
        _viewModelList.Add(ViewModelLocator.Instance.View2);
        _viewModelList.Add(ViewModelLocator.Instance.View3);

        _currentPageViewModel = _viewModelList[0];
    }

    private void ChangePageAction(AViewModel viewModel)
    {
        CurrentPageViewModel = ViewModelList.FirstOrDefault(vm => vm == viewModel);
    }
}

Wir haben hier einen Command zum Wechseln der Seite. Eine Eigenschaft, welche das aktuelle ViewModel enthält, sowie eine List der verfügbaren ViewModels. Im Konstruktor legen wir die Liste an, setzen das erste ViewModels als Default und erstellen den Command.

Der Command nimmt einfach den Parameter, welcher vom Typ AViewModel sein muss, und weist dieses aus der Liste der Eigenschaft “aktuelles ViewModel” zu.

XAML-Code des Hauptfensters

Soweit so gut, schauen wir uns nun die GUI an. Die verfügbaren Seiten, bzw. deren Buttons, stellen wir über ein ItemControl dar:

<ItemsControl DockPanel.Dock="Left"
              ItemsSource="{Binding ViewModelList}"
              Margin="10"
              MinWidth="150">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Button Content="{Binding Name}"
                    Command="{Binding DataContext.ChangePageCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
                    CommandParameter="{Binding }"
                    Margin="0,10,0,0"
                    HorizontalAlignment="Stretch"></Button>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

Neue Seiten können so einfach über die Liste des ViewModels hinzugefügt werden. Der Button wird an das Command des ViewModels gebunden. Als Parameter wird das aktuelle ViewModel übergeben.

Die Darstellung der Seiten erfolgt in einem ContentControl:

<ContentControl x:Name="Content" Content="{Binding CurrentPageViewModel}"></ContentControl>

Dieses wird an das aktuelle ViewModel für die jeweilige Seite gebunden. Damit das ControlControl weiß, was es darstellen soll, erstellen wir für jedes ViewModel ein DataTemplate.

<Window.Resources>
    <DataTemplate DataType="{x:Type vm:View1ViewModel}">
        <local:View1></local:View1>
    </DataTemplate>
    <DataTemplate DataType="{x:Type vm:View2ViewModel}">
        <local:View2></local:View2>
    </DataTemplate>
    <DataTemplate DataType="{x:Type vm:View3ViewModel}">
        <local:View3></local:View3>
    </DataTemplate>
</Window.Resources>

Für jede Seite wird ein UserControl erstellt, welches wir hier im DataTemplate verwenden. Fertig! Mit jedem Button-Klick wird nun zwischen den Seiten der Anwendung gewechselt.

Download des Beispielprojekts

Kommentar hinterlassen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.