WPF MVVM并将视图模型传递给视图

时间:2014-09-02 07:50:38

标签: wpf mvvm

我是WPF的新手,现在我正在尝试习惯MVVM模式。现在我有一个简单的应用程序,其中我有一个ViewModel集合,我在网格中显示。当我双击网格中的行时,我想显示ViewModel的详细信息。

我现在遇到的问题是我已经有一个完全实例化的ViewModel,但我似乎无法将其传递给视图。当我尝试加载该视图时,它变为空白。我已经发现这是因为当View加载时它会创建它自己的后备ViewModel实例。显然,我需要绕过这种行为,并以某种方式将实例化的ViewModel传递给View。我可以在View中使用构造函数来获取ViewModel并在其中设置数据源。但是,采用这种方法但意味着我需要在ViewModel中构造View,从而使ViewModel知道View。这是我想要避免的事情,因为我试图维护MVVM模式。

那么在这种情况下该怎么做?我应该打破MVVM模式还是有一些适合MVVM模式的漂亮而干净的解决方案?

3 个答案:

答案 0 :(得分:4)

传递视图模型到视图的方法有多种,或者将视图模型设置为DataContext或{的Window {1}},正如其他人可能称之为的那样。最简单的就是:

在视图构造函数中:

UserControl

更多MVVM方法可能是为每个视图模型在public partial class SomeView { InitializeComponent(); DataContext = new SomeViewModel(); } 中定义DataTemplate,定义每个视图将使用哪个视图:

App.xaml

现在,只要Framework遇到这些视图模型类的实例,它就会呈现关联的视图。您可以使用<DataTemplate DataType="{x:Type YourViewModelsPrefix:YourViewModel"> <YourViewsPrefix:YourView /> </DataTemplate> ... <DataTemplate DataType="{x:Type YourViewModelsPrefix:AnotherViewModel"> <YourViewsPrefix:AnotherView /> </DataTemplate> 这样的属性来显示它们:

ContentControl

甚至在这样的集合中:

<ContentControl Content="{Binding YourViewModelProperty}" />

答案 1 :(得分:2)

  

&#34;我应该打破MVVM模式吗?&#34;

那么,请考虑更多地了解这种模式,了解它的含义,并打破它#34;。此模式的主要目的是保持责任明确,从而获得可测试和可维护的代码。在这个问题中显示了很多资源: MVVM: Tutorial from start to finish?

无论如何要更具体地说明你的问题,你要找的是如何设置DataContext。

  

&#34;以某种方式将实例化的ViewModel传递给View中的#34;

是的,你得到它,如果你在视图的构造函数中为dataContext分配了一个viewModel,它可以工作但只有在viewModel负责创建视图时才可以接受(这在真的可以接受)几点情况)。您甚至可以编写类似的东西直接从视图外部设置DataContext:

var l_window = new MyView { DataContext = new MyViewModel() };
l_window.Show();

当然主要的缺点是这段代码不可测试。如果您想测试它,您应该使用可模拟服务来管理视图创建。

更常见的解决方案是使用IOC容器(如prism)注入dataContext。您可以在软件启动时创建所有必需的ViewModel,并将它们存储在此IOC容器中。然后,在创建视图时,您要求此容器为您提供viewModel的实例。

示例可以是:在PRISM中导出viewModel:

[Export]
public class MyViewModel {...}

然后在您的视图中导入它:

[Import]
private MyViewModel ViewModel
{
set { this.DataContext = value; }
get { return this.DataContext as MyViewModel; }
}

希望它有所帮助。

答案 2 :(得分:0)

我同意@ Sheridan的回答,并且只想添加另一种方法来使用视图模型实例化视图:您可以使用工厂模式,也许是这样:

public class ViewFactory
{
    public UIElement Create(object context)
    {
        // Create the view model
        // You can pass in various information by parameters
        // as I do with context (Constructor Injection)
        var viewModel = new ViewModel(context);

        // Create the view and set the view model as data context
        var view = new View { DataContext = viewModel };
        return view;
    }
}

您可以在视图模型的方法中调用此工厂,然后将其分配给例如绑定到UI的数据的属性。这样可以提高灵活性 - 但@ Sheridan的解决方案也很好。