通常在执行此类操作时,我会将对话窗口的打开交给一个服务,该服务可以稍后被模拟以进行测试。比如:
public interface IDialogProvider
{
bool OpenDialog(IViewModel viewModel)
}
然后可以将传入的viewmodel绑定为模态窗口的DataContext,并通过数据模板使用正确的视图。
当命令被触发打开子视图时,父视图模型可以使用该服务。孩子可以进行所需的所有处理,并且可以从孩子那里获得任何所需的信息以得出真实的结果:
public void ExecuteEdit()
{
ChildViewModel childViewModel = GetViewModelForSelectedItem();
if (_dialogProvider.OpenDialog(childViewModel)
{
//child view model saved, trigger rebinding etc...
}
}
如果您有这些对话框使用的视图模型的特定基类,要处理错误情况,您可以在后面添加一些代码来处理窗口的关闭。我会在视图模型中使用与视图无关的事件,并在触发此事件时关闭窗口。在视图中:
public DialogWindowView()
{
InitializeComponent();
DataContexctChanged += HandleDataContextChanged;
}
private void HandleDataContextChanged(object sender, EventArgs e)
{
IDialogViewModel viewModel = DataContext as IDialogViewModel;
if (viewModel != null)
{
viewModel.ActionSuccessful += HandleActionSuccessful
}
}
private void HandleActionSuccessful(object sender, EventArgs e)
{
DialogResult = DialogResult.OK;
Close();
}
我对这个代码作为视图完全没有问题,因为视图模型不负责处理事物的外观,包括打开或关闭窗口。如果您完全反对隐藏代码的想法,或者您不想将视图耦合到视图模型类型,则可以将责任转移到 DialogProvider:
public class DialogProvider : IDialogProvider
{
public bool OpenDialog(IDialogViewModel viewModel)
{
Window dialog = new DialogWindow();
dialog.DataContext = viewModel;
bool success = false;
viewModel.ActionSuccessful = (o, e) =>
{
dialog.Close();
success = true;
}
dialog.ShowDialog();
return success;
}
}