我是WPF的新手,现在我正在尝试习惯MVVM模式。现在我有一个简单的应用程序,其中我有一个ViewModel集合,我在网格中显示。当我双击网格中的行时,我想显示ViewModel的详细信息。
我现在遇到的问题是我已经有一个完全实例化的ViewModel,但我似乎无法将其传递给视图。当我尝试加载该视图时,它变为空白。我已经发现这是因为当View加载时它会创建它自己的后备ViewModel实例。显然,我需要绕过这种行为,并以某种方式将实例化的ViewModel传递给View。我可以在View中使用构造函数来获取ViewModel并在其中设置数据源。但是,采用这种方法但意味着我需要在ViewModel中构造View,从而使ViewModel知道View。这是我想要避免的事情,因为我试图维护MVVM模式。
那么在这种情况下该怎么做?我应该打破MVVM模式还是有一些适合MVVM模式的漂亮而干净的解决方案?
答案 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的解决方案也很好。