【发布时间】:2018-07-27 21:59:48
【问题描述】:
我正在使用 Mahapps.Metro 开发一个 WPF 应用程序,这是一个提供“现代”UI 样式的 Nuget 包。
我创建了一个对话框,它是您在左侧选择一个项目,单击右箭头按钮,该项目移动到右侧的选择对话框之一。
我的对话框中的一个验证规则是,在您按下按钮之前必须至少选择一个项目,因此(在我的视图背后的代码中)我打开一个消息框并通知用户,如果他没有t 至少选择一项:
private void AddButton_Click(object sender, RoutedEventArgs e)
{
if (!IsAnySelected(Users))
{
// MetroWindow call
this.ShowMessageAsync("Permissions", "Please select a User.");
return;
// Call ViewModel `AddPermissions()` method here.
}
}
bool IsAnySelected(DataGrid dataGrid)
{
foreach(dynamic d in dataGrid.ItemsSource)
{
if (d.IsSelected) return true;
}
return false;
}
(DataGrid 绑定到 ViewModel 中的 ObservableCollection)
由于 WPF 中的普通消息框无法设置样式,因此 Mahapps 提供了自己的样式。正是在这里,我发现当我尝试在视图中打开消息框时,MahApps 会引发空引用异常。这与我的设置有关,因为他们的演示工作正常。
原来有人提供了一种打开Mahapps消息框in the View Model instead of the view.的方法我的问题是,你为什么要这样做?
View 不对任何视觉元素(包括消息框)负责吗?验证不是 View 的 Code Behind 中允许做的一件事吗?
请注意,这种方法会导致新的问题,即您现在需要一种方法来fire the View Model's method or ICommand from CodeBehind:
(DataContext as SecurityDialogViewModel).AddPermissions();
【问题讨论】:
-
打开消息框类似于发出
Command,Command将由 ViewModel 处理。在这种情况下,该命令用于打开对话框。这没什么错,因为这是 ViewModel 的责任。 -
@CodingYoshi:当然可以,但是出于验证目的,我无法访问 ViewModel 中的表单控件。相反,我将不得不依赖 View Model 的数据绑定
ObservableCollection中的IsSelected字段的值(这是一种可行的,如果迂回的方法,但我的直觉仍然认为 ViewModel 没有业务站立 UI成分)。 Mahapps 人在 ViewModel 中提出的用于执行此操作的技术将 Mahapps.Metro 与 ViewModel 紧密绑定,对此我也不感到兴奋。 -
即使您可以访问控件,在 VM 中使用它也不是一个好主意,因为您的 VM 会与 UI 元素耦合。换句话说,您将无法对其进行单元测试。所以使用
IsSelected非常好。虚拟机协调工作,所以我认为如果它是站立的 UI 组件很好(你可以在两者之间创建另一个项目并将其称为协调器或其他东西,但我不会)。对于模式,讨论可以来回进行,争论的任何一方都会有优势。如果我在 VM 中执行此操作,我将确保在所有屏幕上保持一致。 -
消息框是一个 UI 元素。如果视图模型正忙于打开模式消息框,你将如何对它进行单元测试?
-
这不是意味着 ViewModel 现在必须知道 View 吗?
标签: c# wpf mvvm mahapps.metro