从原则上说ViewModel中不应该获取View的信息,但是事实是在特殊场合需要,比如正确提交后需要关闭判断,如果ViewModel+View的后置代码实现比较麻烦,希望在ViewModel中一并完成。我在网上看到MVVM Light框架中有一种方法可以实现,但必须使用它的dll,为了尽量少用第三方dll的情况下。我使用了自己的方式来实现。 OK,现在就介绍一下我的经验。
在MVVM中轻松实现Command绑定(三)中,我介绍了一种万能Command绑定,我们就利用这个进行扩展。现在,就实现关闭窗口时Window.Closing事件的额外参数中允许取消关闭。
实现思路:
1.在窗体加载时,将Window作为参数传递到ViewModel中;
2.在ViewModel中添加Window的Closing事件,此时就能得到EventArgs参数;
3.当窗体触发Closing事件时,ViewModel中定义的事件处理方法就能起效。
步骤:
1.Window窗体的xaml,注意<i:Interaction>需要使用Blend的System.Windows.Interactivity.dll文件。在Loaded事件中传递了window参数,该参数是<Window>的Name或者x:Name。
- <Window x:Class="WpfApplication1.Window3_EventArgs"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
- xmlns:vm="clr-namespace:WpfApplication1"
- Title="Window3_EventArgs" Height="300" Width="300"
- x:Name="window">
- <Window.DataContext>
- <vm:Window3_ViewModel />
- </Window.DataContext>
- <Grid>
- <TextBlock Text="请点击关Closing" />
- </Grid>
- <i:Interaction.Triggers>
- <i:EventTrigger EventName="Loaded">
- <i:InvokeCommandAction Command="{Binding LoadedCommand}" CommandParameter="{Binding ElementName=window}" />
- </i:EventTrigger>
- </i:Interaction.Triggers>
- </Window>
<Window x:Class="WpfApplication1.Window3_EventArgs"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:vm="clr-namespace:WpfApplication1"
Title="Window3_EventArgs" Height="300" Width="300"
x:Name="window">
<Window.DataContext>
<vm:Window3_ViewModel />
</Window.DataContext>
<Grid>
<TextBlock Text="请点击关Closing" />
</Grid>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<i:InvokeCommandAction Command="{Binding LoadedCommand}" CommandParameter="{Binding ElementName=window}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Window>
2.ViewModel,注意DelegateCommand需要Prism中的Microsoft.Practices.Prism.dll。在LoadedCommand中给win添加Closing事件。
注:Closing事件我采用的Lambda委托的语法,sender和e分别是该事件的两个参数,该事件完整签名是void win_Closing(object sender, System.ComponentModel.CancelEventArgs e) 。当然如果你需要的话,可以写成方法。
- public class Window3_ViewModel {
- public ICommand LoadedCommand {
- get {
- return new DelegateCommand<Window>(win => {
- win.Closing += (sender, e) => {
- if (MessageBox.Show("确认要关闭窗口吗?", "提示", MessageBoxButton.YesNo) == MessageBoxResult.No) {
- e.Cancel = true;
- }
- };
- });
- }
- }
- }
public class Window3_ViewModel {
public ICommand LoadedCommand {
get {
return new DelegateCommand<Window>(win => {
win.Closing += (sender, e) => {
if (MessageBox.Show("确认要关闭窗口吗?", "提示", MessageBoxButton.YesNo) == MessageBoxResult.No) {
e.Cancel = true;
}
};
});
}
}
}
运行效果如图: