C# 命令绑定到视图中带有确认逻辑的ViewModel
正在寻找最优雅的解决方案,将按钮命令绑定到ViewModel ICommand属性,同时允许在视图中进行确认 我想做的是:C# 命令绑定到视图中带有确认逻辑的ViewModel,c#,wpf,mvvm,mvvm-light,icommand,C#,Wpf,Mvvm,Mvvm Light,Icommand,正在寻找最优雅的解决方案,将按钮命令绑定到ViewModel ICommand属性,同时允许在视图中进行确认 我想做的是: 仅允许用户在需要时单击按钮 单击按钮时,请确认 如果确认,请在ViewModel中工作,否则取消 不要破坏MVVM体系结构 通过显示ViewModel中的消息框,可以满足确认要求。然而,我不认为这是一条路要走。它不会破坏MVVM吗?如果CanExecute取决于UI(代码隐藏)和ViewModel的状态,该怎么办?另外,当从ViewModel中弹出messagebox时,可
视图(代码隐藏)
公共部分类主窗口:窗口
{
私有只读MainViewModel _viewModel=new MainViewModel();
公共主窗口()
{
初始化组件();
}
public MainViewModel ViewModel{get{返回此。\u ViewModel;}}
public ICommand SaveCommand{get{返回新的RelayCommand(this.Save,this.CanSave);}
私有bool CanSave(int templateId)
{
返回此值。_viewModel.SaveCommand.CanExecute(null);
}
私有void保存(int templateId)
{
var messageBoxResult=MessageBox.Show(“是否要覆盖?”,“覆盖?”,MessageBoxButton.ok取消);
if(messageBoxResult==messageBoxResult.Cancel)
返回;
//调用方法隐藏主网格并将SelectTemplateUserControl设置为visible。。
}
私有void SelectTemplate\u OnTemplateSelected(对象发送方,int-templateId)
{
这是._viewModel.SaveCommand.Execute(templateId);
}
}
视图模型
public类MainViewModel:ViewModelBase
{
public ICommand SaveCommand{get{返回新的RelayCommand(this.Save,this.CanSave);}
私有bool CanSave(int templateId)
{
//可以保存逻辑,返回布尔值
}
私有void保存(int templateId)
{
//保存逻辑。。。。
}
}
我认为它很好地遵循了MVVM模式,它还实现了单一责任。但这是最好的方法吗?还有其他的可能性吗
通过显示ViewModel中的消息框,可以满足确认要求。然而,我不认为这是一条路要走。它不会破坏MVVM吗
在使用与视图相关的依赖项(如“MessageBox”)时,保留MVVM样式的一种方法是将它们封装并注入视图模型。因此,您可以通过在构造函数中请求IDialogService
来表示依赖关系:
public class MainViewModel : ViewModelBase
{
private readonly IDialogService _dialog;
public MainViewModel(IDialogService dialog)
{
_dialog = dialog;
}
}
然后从视图中传入实现:
private readonly MainViewModel _viewModel = new MainViewModel(new DialogService());
该接口封装了您需要的任何功能,因此可能需要“警报”、“确认”等
并使用MessageBox
或任何其他方法实现它(并为单元测试切换虚拟实现):
这样,您可以将所有确认逻辑从视图移动到视图模型,其中“Save”方法如下所示:
private void Save()
{
if (!_dialog.Confirm("Do you want to overwrite?", "Overwrite?"))
return;
this.SaveCommand.Execute(null);
}
如果CanExecute取决于UI(代码隐藏)和ViewModel的状态,该怎么办
如果您关心测试,那么
CanExecute
所依赖的任何东西都不应该出现在代码背后——您应该将类似的东西移到视图模型中。也许该链接可以帮助您找到很好的解决方案,谢谢。但有一种情况,我认为仍然需要在不影响可测试性的情况下从视图中添加功能。用户已在窗口2中打开文档。当文档未处于“完成状态”时,“应用模板”按钮应亮起,因此ApplyTemplateCommand.CanExecute来自ViewModel 3。一个消息框弹出“覆盖…?”4。如果用户回答是,DocumentUserControl将折叠,SelectTemplateUserControl将显示在窗口5中。当用户选择模板时,视图中会触发ApplyTemplateCommand.Execute(templateId)。我只能想到我的解决方案在这里应用,将对MessageBox的直接调用替换为IDialogService。在这种情况下,还有其他方法适合您的解决方案吗?@RamonBertrand那么您是说在这种情况下,“ApplyEmplateCommand”需要出现在视图中吗?如果没有更多的细节,我想我无法理解你的论点。我建议更新你的问题,突出重点(或者,如果这个新场景与当前问题有足够大的不同,你可以自由地提出一个新问题)。更新代码,以便更清楚地表达我的问题。没有在我的示例中添加DialogService,因为该部分已经回答。
public class MainViewModel : ViewModelBase
{
private readonly IDialogService _dialog;
public MainViewModel(IDialogService dialog)
{
_dialog = dialog;
}
}
private readonly MainViewModel _viewModel = new MainViewModel(new DialogService());
public interface IDialogService
{
bool Confirm(string message, string caption = "Confirm");
}
public class DialogService : IDialogService
{
public bool Confirm(string message, string caption)
{
return MessageBox.Show(message, caption, MessageBoxButton.OKCancel) == MessageBoxResult.OK;
}
}
private void Save()
{
if (!_dialog.Confirm("Do you want to overwrite?", "Overwrite?"))
return;
this.SaveCommand.Execute(null);
}