Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF Navigation using MVVM

Tags:

c#

.net

mvvm

wpf

I'm trying to follow the answer provided in this post, but I must be missing something trivial. I've defined my DataTemplates as App.xaml as follows:

<Application.Resources>
    <DataTemplate DataType="{x:Type vm:BlowerViewModel}">
        <v:BlowerView />
    </DataTemplate>
    <DataTemplate DataType="{x:Type vm:HomeViewModel}">
        <v:HomeView />
    </DataTemplate>
</Application.Resources>

Then, in my MainWindow.xaml I've defined the following code:

<Window x:Class="App.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:vm="clr-namespace:App.UI.ViewModel"
        Title="MainWindow" SizeToContent="WidthAndHeight">
    <Window.DataContext>
        <vm:MainViewModel />
    </Window.DataContext>
    <ContentControl Content="{Binding CurrentView}" />
</Window>

The code for MainViewModel contains a property CurrentView and an ICommand so I can switch views. Defined as follows:

public class MainViewModel : BaseViewModel
{
    private BaseViewModel _currentView;

    public MainViewModel()
    {
        CurrentView = new HomeViewModel();
    }

    public BaseViewModel CurrentView
    {
        get { return _currentView; }
        set
        {
            if (_currentView != value)
            {
                _currentView = value;
                RaiseChangedEvent("CurrentView");
            }
        }
    }

    public ICommand SwitchView { 
        get {
            return new CommandHandler(() => SwitchBlower());
        }
    }

    protected void SwitchBlower()
    {
        CurrentView = new BlowerViewModel(); 
    }
}

In my HomeView.xaml, I have defined a button that links to the MainViewModel to execute the SwitchView ICommand. This is shown below.

<UserControl x:Class="App.UI.View.HomeView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:vm="clr-namespace:App.UI.ViewModel"
        Height="300" Width="300">
    <Grid>
        <TextBlock>This is the homeview</TextBlock>
        <Button Command="{Binding DataContext.SwitchView, RelativeSource={RelativeSource AncestorType={x:Type vm:MainViewModel}}, Mode=OneWay}" Content="Test" />
    </Grid>
</UserControl>

When I start the application it doesn't register the event, and clicking on the button does not fire the event to change the view. I've tried putting breakpoints in both the ICommand get and the function call itself. At first, I thought maybe I needed to define MainViewModel in my data templates, but doing so results in the following error (even though the project builds fine)

Can't put a Window in a style

Can anyone provide the missing piece I need to get this working?

like image 393
entropic Avatar asked Sep 27 '22 14:09

entropic


1 Answers

The AncestorType should be MainWindow not MainViewModel. MainViewModel is not a class that is part of the visual tree.

like image 166
Lee O. Avatar answered Oct 11 '22 15:10

Lee O.