ViewModel应该如何关闭表单?

我试图学习WPF和MVVM的问题,但遇到了一个麻烦。 这个问题是相似的,但不完全相同,这个(处理对话框在WPF,与mvvm) …

我有一个使用MVVM模式编写的“登录”表单。

这个表单有一个ViewModel,它保存着用户名和密码,这些用户名和密码被绑定到XAML中使用普通数据绑定的视图。 它还有一个“登录”命令,绑定到表单上的“登录”按钮,使用普通的数据绑定。

当“Login”命令触发时,它调用ViewModel中的一个函数,该函数关闭并通过网络发送数据以进行登录。当此函数完成时,有两个操作:

  1. 登录无效 – 我们只是显示一个MessageBox,一切正常

  2. 登录是有效的,我们需要关闭登录表单,并返回true作为其DialogResult

问题是,ViewModel对实际的视图一无所知,所以怎么关闭视图并告诉它返回一个特定的DialogResult? 我可以在CodeBehind中粘贴一些代码,并且/或者将视图传递给ViewModel,但是这看起来好像会彻底击败MVVM的全部…


更新

最后,我刚刚违反了MVVM模式的“纯度”,并让View发布了一个Closed事件,并公开了一个Close方法。 ViewModel然后会调用view.Close 。 该视图只有通过一个接口才知道,并通过一个IOC容器连接起来,所以没有可测试性或可维护性的损失。

接受的答案是-5票,这似乎相当愚蠢! 虽然我很清楚自己在“纯”的时候解决问题的好感,但我并不是唯一一个认为200行事件,命令和行为只是为了避免单行“模式”和“纯度”的名字有点荒谬….

我受到了Thejuan的回答 ,写了一个简单的附加属性。 没有风格,没有触发器; 相反,你可以这样做:

 <Window ... xmlns:xc="clr-namespace:ExCastle.Wpf" xc:DialogCloser.DialogResult="{Binding DialogResult}"> 

这几乎就像WPF团队得到正确的清理,并使DialogResult成为一个依赖属性。 只要放一个bool? DialogResult 你的ViewModel上的bool? DialogResult属性和实现INotifyPropertyChanged,你的ViewModel可以通过设置一个属性关闭窗口(并设置其DialogResult)。 MVVM,因为它应该是。

以下是DialogCloser的代码:

 using System.Windows; namespace ExCastle.Wpf { public static class DialogCloser { public static readonly DependencyProperty DialogResultProperty = DependencyProperty.RegisterAttached( "DialogResult", typeof(bool?), typeof(DialogCloser), new PropertyMetadata(DialogResultChanged)); private static void DialogResultChanged( DependencyObject d, DependencyPropertyChangedEventArgs e) { var window = d as Window; if (window != null) window.DialogResult = e.NewValue as bool?; } public static void SetDialogResult(Window target, bool? value) { target.SetValue(DialogResultProperty, value); } } } 

我也在我的博客上发布了这个。

从我的角度来看,这个问题是相当不错的,因为同样的方法不仅用于“登录”窗口,而且用于任何类型的用户。 我已经通过了很多的建议,没有人可以为我。 请参阅我的类,这是从MVVM的设计模式文章 。

每个ViewModel类应该从具有CloseCommand WorkspaceViewModelICommand类型的CloseCommand属性继承。 CloseCommand属性的默认实现会引发CloseCommand事件。

为了让窗口关闭,你的窗口的OnLoaded方法应该被忽略:

 void CustomerWindow_Loaded(object sender, RoutedEventArgs e) { CustomerViewModel customer = CustomerViewModel.GetYourCustomer(); DataContext = customer; customer.RequestClose += () => { Close(); }; } 

或你的应用程序的OnStartup方法:

  protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); MainWindow window = new MainWindow(); var viewModel = new MainWindowViewModel(); viewModel.RequestClose += window.Close; window.DataContext = viewModel; window.Show(); } 

我猜WorkspaceViewModel中的CloseCommand事件和CloseCommand属性实现是非常清晰的,但是我将显示它们是一致的:

 public abstract class WorkspaceViewModel : ViewModelBase // There are nothing interest in ViewModelBase, it only implements INotifyPropertyChanged interface only { RelayCommand _closeCommand; public ICommand CloseCommand { get { if (_closeCommand == null) { _closeCommand = new RelayCommand( param => Close(), param => CanClose() ); } return _closeCommand; } } public event Action RequestClose; public virtual void Close() { if ( RequestClose!=null ) { RequestClose(); } } public virtual bool CanClose() { return true; } } 

RelayCommand的源代码:

 public class RelayCommand : ICommand { #region Constructors public RelayCommand(Action<object> execute, Predicate<object> canExecute) { if (execute == null) throw new ArgumentNullException("execute"); _execute = execute; _canExecute = canExecute; } #endregion // Constructors #region ICommand Members [DebuggerStepThrough] public bool CanExecute(object parameter) { return _canExecute == null ? true : _canExecute(parameter); } public event EventHandler CanExecuteChanged { add { CommandManager.RequerySuggested += value; } remove { CommandManager.RequerySuggested -= value; } } public void Execute(object parameter) { _execute(parameter); } #endregion // ICommand Members #region Fields readonly Action<object> _execute; readonly Predicate<object> _canExecute; #endregion // Fields } 

PS不要因为这些消息来源而严重对待我,如果我昨天有这样的消息,可以节省我几个小时的时间。

PPS欢迎任何意见或建议。

我用附加的行为来关闭窗口。 绑定您的ViewModel“信号”属性到附加的行为(我实际上使用触发器)当它被设置为true,行为关闭窗口。

http://adammills.wordpress.com/2009/07/01/window-close-from-xaml/

有很多评论在这里讨论MVVM的优缺点。 对我而言,我同意尼尔; 这是适当使用模式的问题,MVVM并不总是适合的。 人们似乎已经愿意牺牲软件设计的所有最重要的原则,只是为了让它适合MVVM。

这就是说,..我认为你的情况可能是一个很好的适合于一些重构。

在大多数情况下,我遇到过,WPF使您可以通过不使用多个Window 。 也许你可以尝试使用Frame和S来代替Windows和DialogResult

在你的情况下,我的建议将是有LoginFormViewModel处理LoginCommand ,如果登录无效,请将LoginFormViewModel上的属性设置为适当的值( false或像UserAuthenticationStates.FailedAuthentication一些枚举值)。 你会做同样的成功登录( true或其他枚举值)。 然后,您将使用一个DataTrigger来响应各种用户身份验证状态,并可以使用一个简单的Setter来更改FrameSource属性。

有你的登录窗口返回一个DialogResult我认为是你困惑的地方; DialogResult实际上是ViewModel的一个属性。 在我对WPF公认的有限的经验中,当某些东西感觉不对时,通常是因为我正在考虑如何在WinForms中做同样的事情。

希望有所帮助。

假设你的登录对话框是第一个被创建的窗口,在你的LoginViewModel类中试试这个:

  void OnLoginResponse(bool loginSucceded) { if (loginSucceded) { Window1 window = new Window1() { DataContext = new MainWindowViewModel() }; window.Show(); App.Current.MainWindow.Close(); App.Current.MainWindow = window; } else { LoginError = true; } } 

我会处理它的方式是在我的ViewModel中添加一个事件处理程序。 当用户成功登录后,我会触发该事件。 在我看来,我会附加到这个事件,当它被解雇,我会关闭窗口。

这是一个简单而干净的解决方案 – 您将一个事件添加到ViewModel,并指示窗口在该事件被触发时关闭。

有关更多详细信息,请参阅我的博客文章, 从ViewModel关闭窗口 。

这是我最初做的,这是工作,但它似乎相当冗长和丑陋(全球静态任何东西都不好)

1:App.xaml.cs

 public partial class App : Application { // create a new global custom WPF Command public static readonly RoutedUICommand LoggedIn = new RoutedUICommand(); } 

2:LoginForm.xaml

 // bind the global command to a local eventhandler <CommandBinding Command="client:App.LoggedIn" Executed="OnLoggedIn" /> 

3:LoginForm.xaml.cs

 // implement the local eventhandler in codebehind private void OnLoggedIn( object sender, ExecutedRoutedEventArgs e ) { DialogResult = true; Close(); } 

4:LoginFormViewModel.cs

 // fire the global command from the viewmodel private void OnRemoteServerReturnedSuccess() { App.LoggedIn.Execute(this, null); } 

后来我删除了所有这些代码,并且让LoginFormViewModel在它的视图上调用了Close方法。 它最终变得更好,更容易遵循。 恕我直言,模式的要点是让人们更容易理解你的应用程序在做什么,在这种情况下,MVVM使得它更难以理解,如果我不使用它,现在是模式。

仅供参考,我遇到了同样的问题,我想我找到了一个不需要全局或静态的工作,虽然它可能不是最好的答案。 我让你们自己决定。

在我的情况下,实例化要显示的窗口(让我们称之为ViewModelMain)的ViewModel也知道LoginFormViewModel(使用上面的情况作为例子)。

所以我所做的就是在类型为ICommand的LoginFormViewModel上创建一个属性(我们称它为CloseWindowCommand)。 然后,在Window上调用.ShowDialog()之前,我将LoginFormViewModel上的CloseWindowCommand属性设置为Window I实例化的window.Close()方法。 然后在LoginFormViewModel里,我所要做的就是调用CloseWindowCommand.Execute()来关闭窗口。

这是一个解决方法/破解我想,但它没有真正打破MVVM模式运作良好。

随意批评这个过程,只要你喜欢,我可以把它! 🙂

这可能是很晚了,但我遇到了同样的问题,我找到了一个适合我的解决方案。

我不知道如何创建一个没有对话框的应用程序(也许这只是一个思维模块)。 所以我和MVVM陷入了僵局,并展示了一个对话框。 所以我遇到了这个CodeProject文章:

http://www.codeproject.com/KB/WPF/XAMLDialog.aspx

这是一个基本上允许一个窗口在另一个窗口的可视化树中的用户控件(在xaml中不允许)。 它也暴露了一个名为IsShowing的布尔型DependencyProperty。

您可以设置一个样式,通常在resourcedictionary中,基本上每当控件的Content属性通过触发器显示对话框时:

 <Style TargetType="{x:Type d:Dialog}"> <Style.Triggers> <Trigger Property="HasContent" Value="True"> <Setter Property="Showing" Value="True" /> </Trigger> </Style.Triggers> </Style> 

在你想要显示对话框的视图中,只需要这个:

 <d:Dialog Content="{Binding Path=DialogViewModel}"/> 

而在你的ViewModel中,你所要做的就是将该属性设置为一个值(注意:ViewModel类必须支持INotifyPropertyChanged以使视图知道发生的事情)。

像这样:

 DialogViewModel = new DisplayViewModel(); 

要将ViewModel与View匹配,你应该在resourcedictionary中有这样的东西:

 <DataTemplate DataType="{x:Type vm:DisplayViewModel}"> <vw:DisplayView/> </DataTemplate> 

所有这一切,你得到一个单行代码来显示对话框。 你得到的问题是你不能真正关闭只有上面的代码对话框。 所以这就是为什么你必须在ViewModel基类中放置一个DisplayViewModel继承的事件,而不是上面的代码,写这个

  var vm = new DisplayViewModel(); vm.RequestClose += new RequestCloseHandler(DisplayViewModel_RequestClose); DialogViewModel = vm; 

然后你可以通过回调来处理对话的结果。

这看起来可能有些复杂,但一旦奠定了基础,这是非常简单的。 再次,这是我的执行,我敢肯定还有其他:)

希望这有助于,它救了我。

好吧,这个问题已经快6年了,我还是不能在这里找到我认为是正确的答案,所以请允许我分享我的“2分钱”…

我其实有两种方法,第一种是简单的,第二种是正确的,所以如果你正在寻找合适的,只要跳过#1跳到#2

1.快速简单(但不完整)

如果我只是一个小项目,我有时只是在ViewModel中创建一个CloseWindowAction

  public Action CloseWindow { get; set; } // In MyViewModel.cs 

无论是视图还是视图后面的代码,我只需设置方法即可调用:

(记住,MVVM是关于View和ViewModel的分离的…… View的代码仍然是View,只要有适当的分离,你不会违反模式)

如果一些ViewModel创建一个新的窗口:

 private void CreateNewView() { MyView window = new MyView(); window.DataContext = new MyViewModel { CloseWindow = window.Close, }; window.ShowDialog(); } 

或者,如果你想在你的主窗口中,只要把它放在你的视图的构造函数下:

 public MyView() { InitializeComponent(); this.DataContext = new MainViewModel { CloseWindow = this.Close }; } 

当你想关闭窗口时,只需在ViewModel上调用Action即可。


2.正确的方法

现在正确的做法是使用棱镜 (恕我直言),所有关于它可以在这里找到 。

您可以创建一个交互请求 ,在新窗口中填入您需要的任何数据,进行中餐,关闭它,甚至接收数据 。 所有这些封装和MVVM批准。 你甚至可以得到关闭窗口的状态 ,就像用户CanceledAccepted (OK按钮)窗口和数据返回,如果你需要的话 。 它有点复杂,并且答案1,但它更加完整,并且是微软推荐的模式。

我给出的链接有所有的代码片段和示例,所以我不打算在这里放置任何代码,只是阅读下载Prism Quick Start的文章并运行它,这很简单,只需要稍微详细一点使其工作,但好处是比关闭一个窗口更大。

你可以让ViewModel公开一个View注册的事件。 然后,当ViewModel决定关闭视图的时候,它会触发导致视图关闭的事件。 如果你想传回一个特定的结果值,那么你将在ViewModel中有一个属性。

 public partial class MyWindow: Window { public ApplicationSelection() { InitializeComponent(); MyViewModel viewModel = new MyViewModel(); DataContext = viewModel; viewModel.RequestClose += () => { Close(); }; } } public class MyViewModel { //...Your code... public event Action RequestClose; public virtual void Close() { if (RequestClose != null) { RequestClose(); } } public void SomeFunction() { //...Do something... Close(); } } 

为什么不把窗口作为命令参数传递?

C#:

  private void Cancel( Window window ) { window.Close(); } private ICommand _cancelCommand; public ICommand CancelCommand { get { return _cancelCommand ?? ( _cancelCommand = new Command.RelayCommand<Window>( ( window ) => Cancel( window ), ( window ) => ( true ) ) ); } } 

XAML:

 <Window x:Class="WPFRunApp.MainWindow" x:Name="_runWindow" ... <Button Content="Cancel" Command="{Binding Path=CancelCommand}" CommandParameter="{Binding ElementName=_runWindow}" /> 

只是添加到大量的答案,我想添加以下内容。 假设你在你的ViewModel上有一个ICommand,并且你想让这个命令关闭它的窗口(或者其他的操作),你可以使用类似下面的方法。

 var windows = Application.Current.Windows; for (var i=0;i< windows.Count;i++ ) if (windows[i].DataContext == this) windows[i].Close(); 

这不是完美的,可能很难测试(因为它很难模拟/存根静态),但比其他解决方案更清洁(恕我直言)。

埃里克

我实现了Joe White的解决方案,但遇到偶尔出现的问题:“ DialogResult只能在创建Window之后设置,并显示为对话框 ”错误。

在View被关闭之后,我一直保持ViewModel的状态,偶尔我会用同一个VM打开一个新的View。 看来,在旧的View之前关闭新的View被垃圾回收导致DialogResultChanged试图在关闭的窗口上设置DialogResult属性,从而引发错误。

我的解决方案是更改DialogResultChanged检查窗口的IsLoaded属性:

 private static void DialogResultChanged( DependencyObject d, DependencyPropertyChangedEventArgs e) { var window = d as Window; if (window != null && window.IsLoaded) window.DialogResult = e.NewValue as bool?; } 

完成这一更改后,任何关闭对话框的附件都将被忽略。

另一个解决方案是在视图模型中使用INotifyPropertyChanged创建属性,如DialogResult,然后在Code Behind中写入:

 public class SomeWindow: ChildWindow { private SomeViewModel _someViewModel; public SomeWindow() { InitializeComponent(); this.Loaded += SomeWindow_Loaded; this.Closed += SomeWindow_Closed; } void SomeWindow_Loaded(object sender, RoutedEventArgs e) { _someViewModel = this.DataContext as SomeViewModel; _someViewModel.PropertyChanged += _someViewModel_PropertyChanged; } void SomeWindow_Closed(object sender, System.EventArgs e) { _someViewModel.PropertyChanged -= _someViewModel_PropertyChanged; this.Loaded -= SomeWindow_Loaded; this.Closed -= SomeWindow_Closed; } void _someViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == SomeViewModel.DialogResultPropertyName) { this.DialogResult = _someViewModel.DialogResult; } } } 

最重要的片段是_someViewModel_PropertyChangedDialogResultPropertyName可以是SomeViewModel一些公共常量字符串。

我使用这种技巧在视图控件中进行一些更改,以防在ViewModel中很难做到这一点。 在ViewModel中的OnPropertyChanged你可以在View中做任何你想要的。 ViewModel仍然是“单元测试”,在代码背后的一些小代码没有任何区别。

在需要关闭窗口的位置,只需将其放置在视图模型中即可:

当当

  foreach (Window window in Application.Current.Windows) { if (window.DataContext == this) { window.Close(); return; } } 

我最终混合了Joe White的答案和Adam Mills的答案中的一些代码,因为我需要在程序创建的窗口中显示一个用户控件。 所以DialogCloser不需要在窗口上,它可以在用户控件本身上

 <UserControl ... xmlns:xw="clr-namespace:Wpf" xw:DialogCloser.DialogResult="{Binding DialogResult}"> 

如果没有附加到窗口本身,DialogCloser将找到用户控件的窗口。

 namespace Wpf { public static class DialogCloser { public static readonly DependencyProperty DialogResultProperty = DependencyProperty.RegisterAttached( "DialogResult", typeof(bool?), typeof(DialogCloser), new PropertyMetadata(DialogResultChanged)); private static void DialogResultChanged( DependencyObject d, DependencyPropertyChangedEventArgs e) { var window = d.GetWindow(); if (window != null) window.DialogResult = e.NewValue as bool?; } public static void SetDialogResult(DependencyObject target, bool? value) { target.SetValue(DialogResultProperty, value); } } public static class Extensions { public static Window GetWindow(this DependencyObject sender_) { Window window = sender_ as Window; return window ?? Window.GetWindow( sender_ ); } } } 

我会走这条路:

 using GalaSoft.MvvmLight; using GalaSoft.MvvmLight.Command; using GalaSoft.MvvmLight.Messaging; // View public partial class TestCloseWindow : Window { public TestCloseWindow() { InitializeComponent(); Messenger.Default.Register<CloseWindowMsg>(this, (msg) => Close()); } } // View Model public class MainViewModel: ViewModelBase { ICommand _closeChildWindowCommand; public ICommand CloseChildWindowCommand { get { return _closeChildWindowCommand?? (_closeChildWindowCommand = new RelayCommand(() => { Messenger.Default.Send(new CloseWindowMsg()); })); } } } public class CloseWindowMsg { } 

我已经阅读了所有的答案,但是我必须说,他们中的大部分都不够好,甚至更糟。

您可以使用DialogService类来处理这个问题,该类负责显示对话框窗口并返回对话框结果。 我已经创建了示例项目来演示它的实现和使用。

这里是最重要的部分:

 //we will call this interface in our viewmodels public interface IDialogService { bool? ShowDialog(object dialogViewModel, string caption); } //we need to display logindialog from mainwindow public class MainWindowViewModel : ViewModelBase { public string Message {get; set;} public void ShowLoginCommandExecute() { var loginViewModel = new LoginViewModel(); var dialogResult = this.DialogService.ShowDialog(loginViewModel, "Please, log in"); //after dialog is closed, do someting if (dialogResult == true && loginViewModel.IsLoginSuccessful) { this.Message = string.Format("Hello, {0}!", loginViewModel.Username); } } } public class DialogService : IDialogService { public bool? ShowDialog(object dialogViewModel, string caption) { var contentView = ViewLocator.GetView(dialogViewModel); var dlg = new DialogWindow { Title = caption }; dlg.PART_ContentControl.Content = contentView; return dlg.ShowDialog(); } } 

这不简单吗? 比EventAggregator或其他类似的解决方案更直接,更可读,最后也更容易调试?

正如你所看到的,在我的视图模型中,我已经使用ViewModel的第一种方法在我的帖子中描述: 在WPF中从ViewModel调用View的最佳实践

当然,在现实世界中, DialogService.ShowDialog必须有更多的选项来配置对话框,例如它们应该执行的按钮和命令。 有这样做的不同方式,但超出范围:)

虽然这并没有回答如何通过视图模型来做到这一点的问题,但是这只显示了如何使用XAML +混合SDK来实现。

我选择从Blend SDK下载并使用两个文件,这两个文件都可以通过NuGet作为微软的一个包装。 这些文件是:

System.Windows.Interactivity.dll和Microsoft.Expression.Interactions.dll

Microsoft.Expression.Interactions.dll为您提供了很好的功能,例如在您的视图模型或其他目标上设置属性或调用方法的能力,以及内部的其他小部件。

一些XAML:

 <Window x:Class="Blah.Blah.MyWindow" ... xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" ...> <StackPanel> <Button x:Name="OKButton" Content="OK"> <i:Interaction.Triggers> <i:EventTrigger EventName="Click"> <ei:ChangePropertyAction TargetObject="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" PropertyName="DialogResult" Value="True" IsEnabled="{Binding SomeBoolOnTheVM}" /> </i:EventTrigger> </Button> <Button x:Name="CancelButton" Content="Cancel"> <i:Interaction.Triggers> <i:EventTrigger EventName="Click"> <ei:ChangePropertyAction TargetObject="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" PropertyName="DialogResult" Value="False" /> </i:EventTrigger> </Button> <Button x:Name="CloseButton" Content="Close"> <i:Interaction.Triggers> <i:EventTrigger EventName="Click"> <!-- method being invoked should be void w/ no args --> <ei:CallMethodAction TargetObject="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" MethodName="Close" /> </i:EventTrigger> </i:Interaction.Triggers> </Button> <StackPanel> </Window> 

Note that if you're just going for simple OK/Cancel behavior, you can get away w/ using the IsDefault and IsCancel properties as long as the window is shown w/ Window.ShowDialog().
I personally had problems w/ a button that had the IsDefault property set to true, but it was hidden when the page is loaded. It didn't seem to want to play nicely after it was shown, so I just am setting the Window.DialogResult property as shown above instead and it works for me.

Here is the simple bug free solution (with source code), It is working for me.

  1. Derive your ViewModel from INotifyPropertyChanged

  2. Create a observable property CloseDialog in ViewModel

     public void Execute() { // Do your task here // if task successful, assign true to CloseDialog CloseDialog = true; } private bool _closeDialog; public bool CloseDialog { get { return _closeDialog; } set { _closeDialog = value; OnPropertyChanged(); } } public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged([CallerMemberName]string property = "") { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(property)); } } 

    }

  3. Attach a Handler in View for this property change

      _loginDialogViewModel = new LoginDialogViewModel(); loginPanel.DataContext = _loginDialogViewModel; _loginDialogViewModel.PropertyChanged += OnPropertyChanged; 
  4. Now you are almost done. In the event handler make DialogResult = true

     protected void OnPropertyChanged(object sender, PropertyChangedEventArgs args) { if (args.PropertyName == "CloseDialog") { DialogResult = true; } } 

Create a Dependency Property in your View /any UserControl (or Window you want to close). 如下所示:

  public bool CloseTrigger { get { return (bool)GetValue(CloseTriggerProperty); } set { SetValue(CloseTriggerProperty, value); } } public static readonly DependencyProperty CloseTriggerProperty = DependencyProperty.Register("CloseTrigger", typeof(bool), typeof(ControlEventBase), new PropertyMetadata(new PropertyChangedCallback(OnCloseTriggerChanged))); private static void OnCloseTriggerChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e) { //write Window Exit Code } 

And bind it from your ViewModel's property :

 <Window x:Class="WpfStackOverflowTempProject.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Width="525" CloseTrigger="{Binding Path=CloseWindow,Mode=TwoWay}" 

Property In VeiwModel :

 private bool closeWindow; public bool CloseWindow { get { return closeWindow; } set { closeWindow = value; RaiseChane("CloseWindow"); } } 

Now trigger the close operation by changing the CloseWindow value in ViewModel. 🙂

 Application.Current.MainWindow.Close() 

Thats enough!