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

Original source