我工作的一个WPF MVVM应用。 我显示在DataGrid中的一些数据。 我有两个按钮来添加和编辑所选择的记录。 我在视图模型数据,我已经表现出另一个窗口(View),并确保的ViewModels应该没有关于视图的信息。 我应该在哪里创建视图和视图模型? 如何取回数据并更新数据网格? 我怎样才能在MVVM实现这一目标? 我们还没有决定使用任何框架,所以我创造我自己的界面。
Answer 1:
注:该结束了相当长的答案-请问我,如果有不清楚的地方
对话窗口的实现是在MVVM设计一个有争议的问题,不同的人用不同的方法。
和你一样,我已经决定不使用任何框架,并用手实现最多的事。 当涉及到对话窗口,我选择以务实约我实现MVVM的,从我的ViewModel内启动对话窗口。 另外,我允许每个对话视图模型具有它被显示在窗口的引用,因此它可以关闭它在适当的时候(下面详细说明)。 这打破了一些严格的MVVM“规则”,但它能够完成任务。
这样做的主要缺点是,它可能会破坏单元测试,如果你正在测试的东西,通过一个对话框去。 但是,你可以走很长的路,而不会在这个问题到现在也没有打扰我呢。
我已经建立了一下对话框的ViewModels,我可以轻松地扩展库的。 这是太多的代码张贴在这里,但我会告诉你的亮点。
基本视图模型的对话框
我的每个对话窗口具有从继承的视图模型DialogViewModelBase
,这是类同我经常ViewModelBase
,它提供了支持INotifyPropertyChanged
等有趣的是这种公开的方法,这是我从哪里启动对话框拨打:
/// <summary>
/// Creates window instance for this dialog viewmodel and displays it, getting the dialog result.
/// </summary>
public void ShowDialogWindow()
{
// This is a property of the DialogViewModelBase class - thus, each DialogViewModel holds a reference to its own DialogWindow:
this.DialogWindow = new Dialogs.Views.DialogWindow();
// Tell the DialogWindow to display this ViewModel:
this.DialogWindow.DataContext = this;
// Launch the Window, using a method of the Window baseclass, that only returns when the window is closed:
this.DialogWindow.ShowDialog();
}
当它的窗口在上面的方法启动将关闭Window.DialogResult
属性设置。 这就是为什么DialogWindow
是的属性DialogViewModelBase
类-当子类对话ViewModel
要关闭对话窗口,它只是设置的结果:
protected void CloseDialogWithResult(bool dialogWindowResult)
{
// Setting this property automatically closes the dialog window:
this.DialogWindow.DialogResult = dialogWindowResult;
}
宿主窗口的对话框查看
所述Dialogs.Views.DialogWindow
该类ShowDialogWindow
方法实例在XAML定义,并且是一个子类Window
。 它有两个重要特征。 第一个是它的主要内容元素是一个简单的ContentControl
结合所述当前上下文。 这让我定义不同的Views
对于不同的子类DialogViewModelBase
和DialogWindow
将举办相应的View
基于上下文的类型:
<ContentControl Content="{Binding}" /> <!-- In reality this is inside a border etc but its simplified here for demonstration -->
在的第二个重要特征DialogWindow
XAML是,它定义了对话Views
与对话去ViewModels
。 下面是一个例子:
<Window.Resources>
<!-- DEFAULT ViewModel-View TEMPLATES -->
<DataTemplate DataType="{x:Type dialogs:YesNoMessageBoxDialogViewModel}">
<views:MessageBoxView />
</DataTemplate>
<DataTemplate DataType="{x:Type dialogs:ErrorDialogViewModel}">
<views:ErrorDialogView/>
</DataTemplate>
</Window.Resources>
所有这一切呢,是我可以定义对话框作为子类DialogViewModelBase
并实施了View
每一个,然后告诉DialogWindow
其中View
其ContentControl
必须显示其对话ViewModel
。
启动一个对话框,并取得成果
下面是从我的应用程序的一个样本ViewModels
,在我启动一个对话窗口,允许用户选择创造一个资产类型:
public void CreateNewAsset()
{
// Instantiate desired Dialog ViewModel:
Dialogs.NewAssetTypeSelectionDialogViewModel dialog = new Dialogs.NewAssetTypeSelectionDialogViewModel();
// Launch Dialog by calling method on Dialog base class:
dialog.ShowDialogWindow();
// Execution will halt here until the Dialog window closes...
// The user's selection is stored in a property on the dialog ViewModel, and can now be retrieved:
CalculatorBase.AssetTypeEnum newAssetType = dialog.AssetType;
switch (newAssetType)
{
// Do stuff based on user's selection...
}
}
PS:我真的应该写这个博客条目-当我这样做,我会在这里发布的链接,博客条目将可能有更完整的代码示例。
Answer 2:
这取决于你是如何处理的数据。 我会认为,在弹出的窗口中所做的更改只有当用户点击像保存在其他情况下,他们应该被丢弃被接受。 所以,首先,我会建议使用MVC方法,因为控制器非常适合此类任务。 你建立它的ViewModels,为它们分配Ø视图,示意见。 虚拟机的只是保存数据和命令,命令执行方法保存在控制器中。 换句话说,你必须负责管理你的虚拟机,并享有单独的类。 你应该看看棱镜框架。 它提供了类似观点regios在那里你可以在运行时注入不同的用户控制,指挥和MVC分层了一起IOC和DI模式框的伟大的事情。