简体   繁体   中英

WPF MVVM binding datacontext best practice

I have been told that best practice for MVVM is to pass the viewmodel to the view so it has no knowledge of the datacontext before runtime. (System 1)

However every post I find passes the viewmodel into the xaml datacontext which doesn't seem ideal for MVVM. (System 2)

What is the best way to bind datacontext in WPF MVVM? How does this affect event handler binding?

Example: I have a combo box linked to an item in my ViewModel. When I use binding system 2, the combobox selection fires the 'ComboChanged' event. When using binding system 1, the combobox selection changes, but the event does not fire. Once the whole page has loaded, the event will trigger when the combo box is changed manually.

Host (System 1):

public override void Initialise()
{
    element = new Plugin(new ViewModel(Credentials));
    element.combobox.SelectedIndex = 0;
}

Plugin (System 1):

public Plugin(ViewModel viewModel)
{
     InitializeComponent();
     ViewModel = viewModel;
     this.DataContext = ViewModel;
     ViewModel.ComboChanged += new EventHandler<ComboChangedEventArgs>(performComboChanged);
}

ViewModel (System 1):

public ViewModel(Credentials credentials)
{
    //Initialisation code
}

Host (System 2):

public override void Initialise()
{
     element = new Plugin(Credentials)
     element.combobox.SelectedIndex = 0;
}

Plugin (System 2):

public Plugin(Credentials credentials)
{
    InitializeComponent();
    ViewModel = ((ViewModel)this.DataContext);
    ViewModel.Credentials = credentials;
    ViewModel.ComboChanged += new EventHandler<ComboChangedEventArgs>(performComboChanged);
}

//Plugin.xaml
<UserControl.DataContext>
    <local:ViewModel/>
</UserControl.DataContext>

ViewModel (System 2):

public ViewModel()
{
    //Initialisation code
}

Thanks in advance

Regarding your event handling implementation :

To make it short :

  • you should never bind event to VM in your code behind or even use your VM in the code behind : presentation and business code would be mixed and if your view changes, you may break your code logic
  • you should never use your view or one of its control into your view model : the VM is the place for business, not for presentation

I always keep in mind this one time in particular when I had to totally reoganize a big complex view (renaming controls, switching from listbox to gridview, reorganizing grid, etc..) : because my MVVM was clean (strict separation of VM/business from view/presentation) i was able to do so without touching any line from my business logic. This would have been a nightmare if I had bound all my control events directly to my view model.

From here you have (at least) two options :

  1. use the interaction library that will enable you to bind a control event to a view model command or method
  2. create your own behavior that will implement this link between a control event and a view model command or property.

This post sums up the interaction option : MVVM events

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM