Pass object from parent view to sub view in MVVM
c#, communication, mvvm, windows, wpf
Solution
Sounds like a good solution to this the EventAggregator pattern. There are some great implementations out there such as that provided by Microsoft Prism or TinyMessenger (very lightweight)
As a code example you would do something like this (using Prism, untested code)
public class ParentViewModel
{
private IEventAggregator eventAggregator;
public ParentViewModel(IEventAggregator eventAggregator)
{
this.eventAggregator = eventAggregator;
}
public void PublishSomeEvent()
{
// When a condition occurs, publish an event any subscribers
// that may be listening
this.eventAggregator.GetEvent<SomeEvent>()
.Publish(new SomeEvent("Hello World!")));
}
}
public class SubViewModel
{
private IEventAggregator eventAggregator;
public SubViewModel(IEventAggregator eventAggregator)
{
eventAggregator.GetEvent<SomeEvent>.SomeEvent(OnSomeEventOccurred);
}
public void OnSomeEventOccurred(SomeEvent arg)
{
// This method called when ParentViewModel publishes the event
Console.WriteLine(arg.OptionalMessage);
}
}
You would need a separate declaration of the event. For instance, I use this
public SomeEvent : CompositePresentationEvent<SomeEvent>
{
public SomeEvent(string optionalMessage)
{
this.optionalMessage = optionalMessage;
}
public string OptionalMessage { get { return optionalMessage; } }
}
Problem
I am currently trying to get into WPF and MVVM, but I recently ran into a problem I don't know how to solve. I am new to this, so if something is not as it should be, please tell me. I have a ParentView with its ParentViewModel. The ParentView holds two views SubViewA and SubViewB which both have their own ViewModels. This is my ParentView.xaml: ``` <local:ViewBase.DataContext> <local:ParentViewModel x:Name="Model" /> </local:ViewBase.DataContext> <Grid> <local:SubViewA Visibility="{Binding ElementName=Model, Path=SubViewAVisibility}" /> <local:SubViewB Visibility="{Binding ElementName=Model, Path=SubViewBVisibility}" /> </Grid> ``` What I want to do: SubViewModelB has a property that is binded to SubViewB. I want to change that property when a certain event occurs in the ParentViewModel. I suppose this should be done by binding the property in SubViewModelB to a property in ParentViewModel, but I'm not really sure how? I tried something like the following in the ParentView.xaml: ``` <local:SubViewB Visibility="{Binding ElementName=Model, Path=SubViewBVisibility}" SomeProperty="{Binding ElementName=Model, Path=WhatIWantThePropertyToBe}" /> ``` but that got me nowhere. So how do I solve this? I know I could do it via messaging in the MVVM light toolkit, but that seems kind of inappropiate for what I am trying to do. Any suggestions? Thanks