WPF MVVM绑定datacontext的最佳实践

时间:2020-12-11 20:17:03

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)

我被告知MVVM的最佳实践是将viewmodel传递给视图,因此它在运行时之前不知道datacontext。 (系统1)

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

但是我发现的每个帖子都将viewmodel传递给xaml datacontext,这对于MVVM来说似乎并不理想。 (系统2)

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

在WPF MVVM中绑定datacontext的最佳方法是什么?这如何影响事件处理程序绑定?

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.

示例:我有一个组合框链接到我的ViewModel中的项目。当我使用绑定系统2时,组合框选择会触发'ComboChanged'事件。使用绑定系统1时,组合框选择会更改,但事件不会触发。加载整个页面后,手动更改组合框时将触发事件。

Host (System 1):

主机(系统1):

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

Plugin (System 1):

插件(系统1):

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

ViewModel (System 1):

ViewModel(系统1):

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

Host (System 2):

主机(系统2):

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

Plugin (System 2):

插件(系统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):

ViewModel(系统2):

public ViewModel()
{
    //Initialisation code
}

Thanks in advance

提前致谢

1 个解决方案

#1


1  

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
  • 你永远不应该在你的代码中将事件绑定到VM,甚至在后面的代码中使用你的VM:演示文稿和业务代码会混合在一起,如果你的视图发生了变化,你可能会破坏你的代码逻辑
  • 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
  • 您永远不应该将您的视图或其中一个控件用于您的视图模型:VM是业务的场所,而不是用于演示

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.

我总是记住这一次,特别是当我不得不完全重新组合一个大的复杂视图(重命名控件,从列表框切换到gridview,重新组织网格等等)时:因为我的MVVM很干净(严格分离VM /业务)从视图/演示文稿)我能够这样做而不触及我的业务逻辑中的任何行。如果我将所有控制事件直接绑定到我的视图模型,那将是一场噩梦。

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. 使用交互库,您可以将控件事件绑定到视图模型命令或方法
  3. create your own behavior that will implement this link between a control event and a view model command or property.
  4. 创建自己的行为,在控件事件和视图模型命令或属性之间实现此链接。

This post sums up the interaction option : MVVM events

这篇文章总结了交互选项:MVVM事件

#1


1  

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
  • 你永远不应该在你的代码中将事件绑定到VM,甚至在后面的代码中使用你的VM:演示文稿和业务代码会混合在一起,如果你的视图发生了变化,你可能会破坏你的代码逻辑
  • 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
  • 您永远不应该将您的视图或其中一个控件用于您的视图模型:VM是业务的场所,而不是用于演示

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.

我总是记住这一次,特别是当我不得不完全重新组合一个大的复杂视图(重命名控件,从列表框切换到gridview,重新组织网格等等)时:因为我的MVVM很干净(严格分离VM /业务)从视图/演示文稿)我能够这样做而不触及我的业务逻辑中的任何行。如果我将所有控制事件直接绑定到我的视图模型,那将是一场噩梦。

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. 使用交互库,您可以将控件事件绑定到视图模型命令或方法
  3. create your own behavior that will implement this link between a control event and a view model command or property.
  4. 创建自己的行为,在控件事件和视图模型命令或属性之间实现此链接。

This post sums up the interaction option : MVVM events

这篇文章总结了交互选项:MVVM事件