robertwojnar
robertwojnar

Reputation: 129

Communication between ViewModel and UserControl's view

I working on WPF MVVM project. I'm struggling with communication between viewmodel of my MainWindow and view of usercontrol, placed inside MainWindow.

So I have:

My UserControl is very simple:

<Grid MouseDown="UIElement_OnMouseDown">
    <Rectangle Fill="BlueViolet" />
</Grid>

with code-behind (just rise an event when rectangle is clicked, and pass coordinates):

public partial class FooUserControl : UserControl
{
    public FooUserControl()
    {
        InitializeComponent();
    }

    public event EventHandler<BarEventArgs> BarClick;
    private void UIElement_OnMouseDown(object sender, MouseButtonEventArgs e)
    {
        double x = e.GetPosition(this).X;
        double y = e.GetPosition(this).Y;
        string value_to_pass = "[" + x + "," + y + "]";

        BarEventArgs bar = new BarEventArgs() { Bar = 2, Foo = value_to_pass };
        BarClick?.Invoke(sender, bar);
    }
}

My MainWindow doesn't have code-behind. Just xaml. As you can see I pass click event via Command to MainWindowViewModel:

<Window.DataContext>
    <viewModels:MainWindowViewModel />
</Window.DataContext>
<Grid>
    <local:FooUserControl>
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="BarClick">
                <cmd:EventToCommand Command="{Binding ClickedCommand}" PassEventArgsToCommand="True" />
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </local:FooUserControl>
</Grid>

and finally my MainWindowViewModel has just this command:

public class MainWindowViewModel : ObservableObject
{
    public ICommand ClickedCommand => new RelayCommand<BarEventArgs>(o => Clicked(o.Foo));
    private void Clicked(string a)
    {
        Debug.WriteLine("Clicked " + a);
    }
}

So, communication from UserControl's view to MainWindow's viewmodel, via command, works great. But, how can I communicate in opposite way? From MainWindowViewModel to UserControl's view?

Upvotes: 3

Views: 3874

Answers (2)

Betson Roy
Betson Roy

Reputation: 141

MVVM says,view should talk only to its viewmodel and viewmodels can talk to other viewmodels only(and model).
What you need is a Mediator. enter image description here
Source : http://dotnetpattern.com/mvvm-light-messenger/
With this you don't have to create event in your usercontrol.you can communicate to any viewmodel that is instantiated. You can use mvvm-light,which provides an implementation of Mediator pattern(Messenger).it also provides other tools that will help you build MVVM application.
here is a tutorial to MVVMLight Messenger.

With binding you can update the view appropriately.
thus viewmodels talk to each other and views are updated by corresponding view.
this way you wont be violating any MVVM principle.

Upvotes: 2

M.E.
M.E.

Reputation: 2929

Your ViewModels should not access your Views directly. They should not care about Views at all. All they do, is, provide properties to make data available. Views can now bind to these properties.

So, all communication from the ViewModel to the View works through Bindings only. When the ViewModel has to tell the View something, it provides a property. Then it's up to the View to bind to that property and do something with it - whatever this might be.

Upvotes: 4

Related Questions