View如何知道在WPF中使用什么ViewModel?

时间:2012-06-21 15:37:07

标签: c# wpf mvvm

有人可以解释View和ViewModel是如何连接的吗?我找不到引用ViewModel的View的xaml或xaml.cs,也没有找到引用View的ViewModel.cs文件中的任何内容,但它们以某种方式连接,并且从ViewModel到View的绑定成员工作。

此外,在每个构造函数中,只有View的InitializeComponent和ViewModel的基本构造函数(没有View的声明/定义)。

谢谢!

4 个答案:

答案 0 :(得分:30)

这里有各种选择。

Something 必须将View的DataContext设置为ViewModel的一个实例。这里有很多选择:

  • 这可以直接在xaml中完成(View直接实例化ViewModel)。
  • 这可以在View的构造函数(this.DataContext = new MyViewModel();
  • 中完成
  • 可以通过DataTemplate
  • 处理
  • “协调”类可以将这些连接在一起(即:单独的“演示者”类可以构造两者并适当地设置DataContext

最常见的是让View在xaml中定义VM(View-first),或者让所有内容都基于ViewModel为中心,并让WPF根据绑定的VM自动创建View (视图模型优先)。

前一种方法是许多工具包使用的方法,例如MVVM Light。后一种方法是我在MVVM blog series中使用的方法,并被其他一些工具包使用。

答案 1 :(得分:5)

将视图连接到视图模型的“干净”方式是......

创建视图时,对于每个视图,将其DataSource设置为其视图模型:

E.g。

public class App
{
    private void OnAppStart()
    {
        var model = new MainModel();
        var vm = new MainVM();
        var view = new MainWindow();

        vm.Model = model;
        view.DataSource = vm;

        view.Show();
    }
}

当您正在查看的模型发生更改时,请更新VM:

public class MainVM
{
    private void OnSelectedModelItemChanged()
    {
        this.SelectedItem = new ItemVM();
        this.SelectedItem.Model = this.SelectedModelItem;
    }
}

使用数据模板为视图选择每个VM的正确子视图。

答案 2 :(得分:2)

视图包含xaml中视图模型类的对象。

InitializeComponent函数在页面上创建所有控件,设置样式等。

答案 3 :(得分:0)

正如其他人已经显示的那样,有多个选项。当然,每当您听到多种选择时,您都不得不想知道每种选择的优缺点。好吧,事实证明,除了一个之外,所有这些都具有主要缺点。

以下方法不涉及任何外部库,不需要其他管家类和接口,几乎没有魔术,并且非常灵活,因为您可以拥有包含其他视图模型的视图模型,并且可以实例化每个视图模型,因此您可以传递构造函数参数。

对于主窗口的视图模型:

using Wpf = System.Windows;

public partial class TestApp : Wpf.Application
{
    protected override void OnStartup( Wpf.StartupEventArgs e )
    {
        base.OnStartup( e );
        MainWindow = new MainView();
        MainWindow.DataContext = new MainViewModel( e.Args );
        MainWindow.Show();
    }
}

对于所有其他视图模型:

这在MainViewModel.cs中:

using Collections = System.Collections.Generic;

public class MainViewModel
{
    public SomeViewModel SomeViewModel { get; }
    public OtherViewModel OtherViewModel { get; }
    public Collections.IReadOnlyList<string> Arguments { get; }
    
    public MainViewModel( Collections.IReadOnlyList<string> arguments )
    {
        Arguments = arguments;
        SomeViewModel = new SomeViewModel( this );
        OtherViewModel = new OtherViewModel( this );
    }
}

在MainView.xaml中

[...]
xmlns:local="clr-namespace:the-namespace-of-my-wpf-stuff"
[...]
    <local:SomeView DataContext="{Binding SomeViewModel}" />
    <local:OtherView DataContext="{Binding OtherViewModel}" />
[...]

如您所见,一个视图模型可以简单地成为另一个视图模型的成员(子)。在这种情况下,SomeViewModel和OtherViewModel是MainViewModel的子级。然后,在MainView的XAML文件中,您只需实例化每个子视图并将DataContext通过Binding指定给相应的子视图模型。