Arne_22
Arne_22

Reputation: 57

How to Call a Method from another ViewModel in a View (WPF)

I have my (Mainwindow) Window.xaml.cs in which i declare a custom closing Event. In that Closing event I would like to call a method from another Views' ViewModel ReportGeneratorViewModel.cs. I don't know how to link those 2 together or call it from there. (The ReportGeneratorView is hosted in a frame control in the Window.xaml)

Normaly my Views.xaml.cs call methods from corresponding ViewModels via

var Context = (ViewModel)DataContext;
Context.CallMethod();

So my Idea was that i just call the DesiredMethod() in my window.xaml.cs like that:

var Context = (ReportGeneratorViewModel)DataContext;
Context.DesiredMethod();

But it throws an exception that "...WindowViewModel" can not be converted to "...ReportGeneratorViewModel".

Is there any way to go about that?

Upvotes: 0

Views: 2954

Answers (2)

thatguy
thatguy

Reputation: 22119

Assuming your Frame is declared like this and has a name in Window.xaml:

<Frame x:Name="myFrame" Source="/Any/Path/ReportGeneratorView.xaml"/>

You use code-behind, you can call the DesiredMethod in the Closing event handler like this:

private void OnClosing(object sender, CancelEventArgs e)
{
   var content = ((FrameworkElement)myFrame.Content);
   var dataContext = (ReportGeneratorViewModel)content.DataContext;

   dataContext.DesiredMethod();
}

A more MVVM friendly way is to use loosely coupled events as @Gimly suggested.

Upvotes: 1

Gimly
Gimly

Reputation: 6175

Usually you try to not have too much links between your view models, so your Main window view model shouldn't be aware of the other view model.

Instead, the "classical" approach to this is to use a "pub-sub" approach where you would have an "event aggregator". The report generator view model would subscribe to the specific event which would be sent by the main view model.

You would have something like that (took and modified from the Prism documentation):

public class MainPageViewModel
{
    IEventAggregator _eventAggregator;

    public MainPageViewModel(IEventAggregator ea)
    {
        _eventAggregator = ea;
    }

    public void SendEvent()
    {
        _eventAggregator.GetEvent<MyEvent>().Publish("Something happening");
    }
}

public class OtherViewModel
{
    public OtherViewModel(IEventAggregator ea)
    {
        ea.GetEvent<MyEvent>().Subscribe(ShowNews);
    }

    void ShowNews(string companySymbol)
    {
        //implement logic
    }
}

Of course, depending on your MVVM framework, the use of the event aggregator might be a little different.

Using this approach gives you a clear separation between your viewmodels and will allow you to send the event from other VMs if needs be in the future.

Upvotes: 3

Related Questions