我正在尝试学习WPF和MVVM问题,但是遇到了障碍.这个问题与此问题相似但不完全相同(处理对话框-wpf-with-mvvm) ...
我有一个使用MVVM模式编写的"登录"表单.
此表单有一个ViewModel,它包含用户名和密码,这些用户名和密码使用普通数据绑定绑定到XAML中的视图.它还有一个"登录"命令,该命令绑定到表单上的"登录"按钮,使用正常数据绑定.
当"登录"命令触发时,它会调用ViewModel中的一个函数,该函数将关闭并通过网络发送数据以进行登录.当此函数完成时,有2个操作:
登录无效 - 我们只显示一个MessageBox,一切都很好
登录有效,我们需要关闭登录表单并让它返回true作为其DialogResult...
问题是,ViewModel对实际视图一无所知,那么如何关闭视图并告诉它返回一个特定的DialogResult?我可以在CodeBehind中粘贴一些代码,和/或将View传递给ViewModel,但这似乎完全打败了MVVM的全部内容......
最后,我刚刚违反了MVVM模式的"纯度",并让View发布了一个Closed事件,并公开了一个Close方法.ViewModel然后才会调用view.Close.该视图仅通过接口已知并通过IOC容器连接,因此不会丢失可测试性或可维护性.
接受的答案是-5票,这似乎很愚蠢!虽然我很清楚通过在"纯粹"时解决问题所获得的良好感受,当然我不是唯一一个认为200行事件,命令和行为只是为了避免单行方法"模式"和"纯度"的名称有点荒谬......
尝试在shell窗口中管理各种视图的VM状态,以及用于多个编辑对话的VM状态,模态或非模态以及窗口本身的状态之间,我经历了太多的痛苦.
现在我希望重做一个shell窗口,并希望只有一个对话窗口,那么我的Windows和Vms的耦合程度要小得多,我可以将shell的VM管理模式借用到对话框的管理中.
我看到了很多关于直接管理弹出窗口和不太普遍的非模态的指导,但是是否有任何既定的模式或指导只使用一个对话来托管各种VM?更好的是,Prism中是否还有这样的功能?
我想真正坚持DRY原则,并且在视图和VM中的继承增加了我无法承受的复杂性,应该是一个快速的第一次迭代原型.
想象一下,你想要一个Save & Close和Cancel & Close你的花式WPF MVVM窗口上的按钮?
你会怎么做?MVVM规定你将按钮绑定到ICommand控制器的反转并指示你View可能知道你的ViewModel但不是相反.
我在网上找到了一个解决方案,它有一个ViewModel结束事件,View订阅如下:
private void OnLoaded(Object sender
, RoutedEventArgs e)
{
IFilterViewModel viewModel = (IFilterViewModel)DataContext;
viewModel.Closing += OnViewModelClosing;
}
private void OnViewModelClosing(Object sender
, EventArgs<Result> e)
{
IFilterViewModel viewModel = (IFilterViewModel)DataContext;
viewModel.Closing -= OnViewModelClosing;
DialogResult = (e.Value == Result.OK) ? true : false;
Close();
}
Run Code Online (Sandbox Code Playgroud)
但是这与我迄今为止设计良好的MVVM混合在一起.
另一个问题是在显示主窗口时显示许可问题消息框.我可以再次使用Window.Loaded像我上面那样的事件,但这也打破了MVVM,不是吗?
在这些情况下,是否有一种干净的方式或者应该是实用的而不是迂腐的?
我发现了这个:Close Window from ViewModel这让我开始修改我的 DelegateCommand 类来处理参数。但我无法解决语法问题。
这是我的 DelegateCommand 类,以及我尝试创建但收效甚微的 DelegateCommand 类:
public class DelegateCommand : ICommand
{
private readonly Action _action;
public DelegateCommand(Action action)
{
_action = action;
}
public void Execute(object parameter)
{
_action();
}
public bool CanExecute(object parameter)
{
return true;
}
#pragma warning disable 67
public event EventHandler CanExecuteChanged { add { } remove { } }
#pragma warning restore 67
}
public class DelegateCommand<T> : ICommand
{
private readonly Action _action;
public DelegateCommand(Action action) …Run Code Online (Sandbox Code Playgroud)