Reputation: 129
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:
UserControl
MainWindow
MainWindowViewModel
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
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.
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
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