Muc*_*low 4 c# wpf mvvm mvvm-light
我知道这个问题已经被问过很多次了,但我会尽量具体。
我是 WPF / MVVM 的初学者,并在我的项目中使用 Galasoft 的 MVVM Light Toolkit。
我有一个包含用户输入一些患者详细信息的表单的视图。当他们单击关闭(X)按钮时,我想检查他们是否输入了某些内容,如果输入了,则询问他们是否要在关闭之前使用(是、否和取消)选项进行保存。我做了一些研究,发现很多人都建议使用 EventToCommand 功能,如下所示,
XAML
<Window
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WPF45"
DataContext="{Binding Main, Source={StaticResource Locator}}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Closing">
<cmd:EventToCommand Command="{Binding OnClosingCommand}"
PassEventArgsToCommand="True"/>
</i:EventTrigger>
</i:Interaction.Triggers>
...
</Window>
Run Code Online (Sandbox Code Playgroud)
查看模型
public class MainViewModel : ViewModelBase
{
public RelayCommand<CancelEventArgs> OnClosingCommand { get; set; }
public MainViewModel()
{
this.OnClosingCommand =
new RelayCommand<CancelEventArgs>(this.OnClosingCommandExecuted);
}
private void OnClosingCommandExecuted(CancelEventArgs cancelEventArgs)
{
// logic to check if view model has updated since it is loaded
if (mustCancelClosing)
{
cancelEventArgs.Cancel = true;
}
}
}
Run Code Online (Sandbox Code Playgroud)
上面的例子取自使用带有 MVVM 灯的“X”按钮关闭窗口时的确认
然而,MVVM Light Toolkit 的创建者本人表示,这打破了 MVVM 模式试图实现的关注点分离,因为它将属于视图(在本例中为 )的事件参数传递CancelEventArgs给视图模型。他在这篇文章中这么说http://blog.galasoft.ch/posts/2014/01/using-the-eventargsconverter-in-mvvm-light-and-why-is-there-no-eventtocommand-in-the- windows-8-1-版本/
所以我的问题是,处理此类问题且不破坏 MVVM 模式的正确方法是什么?任何正确方向的观点将不胜感激!
我并不是假装绝对真理,但我喜欢遵循以下方法。
基本视图模型有一个RelayCommand/ ,DelegateCommand如下所示:
public ICommand ClosingCommand { get; }
Run Code Online (Sandbox Code Playgroud)
其中ICommand.Execute实现为:
/// <summary>
/// Executes an action, when user closes a window, displaying this instance, using system menu.
/// </summary>
protected virtual void Closing()
{
}
Run Code Online (Sandbox Code Playgroud)
并ICommand.CanExecute作为:
/// <summary>
/// Detects whether user can close a window, displaying this instance, using system menu.
/// </summary>
/// <returns>
/// <see langword="true"/>, if window can be closed;
/// otherwise <see langword="false"/>.
/// </returns>
protected virtual bool CanClose()
{
return true;
}
Run Code Online (Sandbox Code Playgroud)
反过来,UI 使用附加行为来处理Window.Closing:
public static class WindowClosingBehavior
{
public static readonly DependencyProperty ClosingProperty = DependencyProperty.RegisterAttached(
"Closing",
typeof(ICommand),
typeof(WindowClosingBehavior),
new UIPropertyMetadata(new PropertyChangedCallback(ClosingChanged)));
public static ICommand GetClosing(DependencyObject obj)
{
return (ICommand)obj.GetValue(ClosingProperty);
}
public static void SetClosing(DependencyObject obj, ICommand value)
{
obj.SetValue(ClosingProperty, value);
}
private static void ClosingChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
{
var window = target as Window;
if (window != null)
{
if (e.NewValue != null)
window.Closing += Window_Closing;
else
window.Closing -= Window_Closing;
}
}
private static void Window_Closing(object sender, CancelEventArgs e)
{
var window = sender as Window;
if (window != null)
{
var closing = GetClosing(window);
if (closing != null)
{
if (closing.CanExecute(null))
closing.Execute(null);
else
e.Cancel = true;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
XAML(假设该视图模型是DataContextfor 窗口):
behaviors:WindowClosingBehavior.Closing="{Binding ClosingCommand}"
Run Code Online (Sandbox Code Playgroud)