WPF MVVM 绑定数据上下文最佳实践

WPF MVVM binding datacontext best practice

有人告诉我,MVVM 的最佳实践是将视图模型传递给视图,这样它在运行前不知道数据上下文。 (系统 1)

然而,我发现每个 post 都会将视图模型传递到 xaml 数据上下文中,这对于 MVVM 来说似乎并不理想。 (系统 2)

在 WPF MVVM 中绑定数据上下文的最佳方法是什么?这对事件处理程序绑定有何影响?

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

主机(系统 1):

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

插件(系统 1):

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

ViewModel(系统 1):

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

主机(系统 2):

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

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

视图模型(系统 2):

public ViewModel()
{
    //Initialisation code
}

提前致谢

关于您的事件处理实现:

简而言之:

  • 你不应该在代码隐藏中将事件绑定到 VM,甚至不应该在代码隐藏中使用你的 VM:表示和业务代码会混合在一起,如果你的视图发生变化,你可能会破坏你的代码逻辑
  • 您永远不应该将您的视图或其控件之一用于您的视图模型:VM 是业务场所,而不是演示场所

有一次我总是牢记这一点,尤其是当我不得不完全重新组织一个大的复杂视图(重命名控件、从列表框切换到网格视图、重新组织网格等)时:因为我的 MVVM 很干净(严格VM/business 与 view/presentation 的分离)我能够做到这一点,而无需触及我的业务逻辑中的任何一行。如果我将所有控件事件直接绑定到我的视图模型,这将是一场噩梦。

从这里你有(至少)两个选择:

  1. 使用交互库,使您能够将控件事件绑定到视图模型命令或方法
  2. 创建您自己的行为以在控制事件和视图模型命令或 属性 之间实现此 link 或 属性。

这个 post 总结了交互选项:MVVM events