1

I think I might be doing something totally wrong here, so hopefully you guys can correct me.

I want to switch Views (switch UserControls inside a Window) using a button, then have the other View be able to have a button that switches back to the first View (like a back button). I've found how to do this using the Google, but the problem I'm running into is that I have my first View's DataContext bound to one ViewModel and the code for switching views is in another, so I can't seem to bind the button in the first View to Bind its Command to that other ViewModel. Here's what I mean (simplified):

FirstView.xaml.cs:

private readonly FirstViewModel viewModel = new FirstViewModel();

public AirplanesStatusView()
{
    InitializeComponent();
    DataContext = viewModel; //Bound to this viewModel for other reasons
}

FirstView.xaml:

<UserControl>
    <Grid>
        <Button Command="{Binding GotoSecondViewCommand}}" //This Command is in other MainWindowViewModel
    </Grid>
</UserControl>

MainWindow.xaml.cs:

private readonly MainWindowViewModel mainWindowViewModel = new MainWindowViewModel();

public MainWindow()
{
    InitializeComponent();
    DataContext = mainWindowViewModel;
}

So then from what I found on Google, this is how it said to approach switching Views: MainWindow.xaml:

<Window>
    <Window.Resources>
        <DataTemplate DataType="{x:Type local:FirstViewModel}">
            <local:FirstView/>
        </DataTemplate>
        <DataTemplate DataType="{x:Type local:SecondViewModel}">
            <local:SecondView/>
        </DataTemplate>
    </Window.Resources>

    <ContentControl Content="{Binding CurrentView}" />
</Window>

MainWindowViewModel.cs:

private ICommand _gotoFirstViewCommand;
private ICommand _gotoSecondViewCommand;
private object _currentView;

public ICommand GotoFirstViewCommand{ //stuff }
public ICommand GotoSecondViewCommand{ //stuff }

public object CurrentView
{
    get { return _currentView; }
    set
    {
        _currentView = value;
        OnPropertyChanged("CurrentView");
    }
}

The problem is when I run the program, in the output it says "System.Windows.Data Error: 40 : BindingExpression path error: 'GotoSecondViewCommand' property not found on 'object' ''FirstViewModel', so the Button can't even find the command. I'm pretty sure I'm doing something totally wrong as I'm pretty new to WPF and the MVVM patter. Help and correction would be greatly appreciated.

3
  • You have to take button command in the viewmodel which you are binding with the user control not to the main window. Commented Feb 7, 2018 at 6:00
  • private readonly FirstViewModel... why is this in your view and not in your MainWindowVM ? That's how you make things more complicated than they are. Commented Feb 7, 2018 at 6:06
  • For your binding in the button you'll have to use RelativeSource to bind it to the parent. Commented Feb 7, 2018 at 6:08

2 Answers 2

2

Try this:

<Button Command="{Binding DataContext.GotoSecondViewCommand, RelativeSource={RelativeSource AncestorType=Window}}"/>

It binds to the DataContext of the parent window, i.e. the MainWindowViewModel where the GotoSecondViewCommand is defined.

Sign up to request clarification or add additional context in comments.

2 Comments

So this works fantastically for the first view's button. It calls the GotoSecondViewCommand in the MainWindowViewModel just like I want, but it doesn't work for the second view's "back" button. I want this "back" button to call the GoToFirstViewCommand in MainWindowViewModel. In the SecondViiew.xaml I did exactly as you said (just changing the Binding to GoToFirstViewCommand), but I get this error:
Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Window', AncestorLevel='1''. BindingExpression:Path=DataContext.GotoFirstViewCommand; DataItem=null; target element is 'Button' (Name='ButtonBack'); target property is 'Command' (type 'ICommand')
0

You are binding wrong ViewModel as DataContext. Based on you structure, you need to do...

  1. Take Command for the Button in FirstViewModel for moving to SecondView.
  2. Take Command for the Button in SecoondViewModel for moving to FirstView.
  3. Remove command from MainViewModel because it is of no use.
  4. Put relative business logic in command execution to transfer the views.
  5. Your CurrentView is nothing but the current user control (either FirstView / Second View)

Another way is if you want to take command in MainViewModel

  1. Take only one ICommand as "ChangeViewsCommand"
  2. Detect the current View either FirstView / Second View) from CurrentView
  3. Transfer to another view which is not active.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.