从ViewModel关闭窗口

时间:2013-04-23 14:49:00

标签: c# wpf mvvm

我使用window control创建登录,以允许用户登录我正在创建的WPF应用程序。

到目前为止,我已经创建了一种方法,用于检查用户是否在登录屏幕上的username中输入了passwordtextbox的正确凭据,{{1两个binding

我通过创建properties方法实现了这一点,就像这样;

bool

我还public bool CheckLogin() { var user = context.Users.Where(i => i.Username == this.Username).SingleOrDefault(); if (user == null) { MessageBox.Show("Unable to Login, incorrect credentials."); return false; } else if (this.Username == user.Username || this.Password.ToString() == user.Password) { MessageBox.Show("Welcome " + user.Username + ", you have successfully logged in."); return true; } else { MessageBox.Show("Unable to Login, incorrect credentials."); return false; } } public ICommand ShowLoginCommand { get { if (this.showLoginCommand == null) { this.showLoginCommand = new RelayCommand(this.LoginExecute, null); } return this.showLoginCommand; } } private void LoginExecute() { this.CheckLogin(); } command bind xaml我的按钮<Button Name="btnLogin" IsDefault="True" Content="Login" Command="{Binding ShowLoginCommand}" /> 就像这样;

dialog modal

当我输入用户名和密码时,它会执行适当的代码,无论是正确还是错误。但是,当用户名和密码都正确时,如何从ViewModel关闭此窗口?

我之前尝试过使用private void ApplicationStart(object sender, StartupEventArgs e) { Current.ShutdownMode = ShutdownMode.OnExplicitShutdown; var dialog = new UserView(); if (dialog.ShowDialog() == true) { var mainWindow = new MainWindow(); Current.ShutdownMode = ShutdownMode.OnMainWindowClose; Current.MainWindow = mainWindow; mainWindow.Show(); } else { MessageBox.Show("Unable to load application.", "Error", MessageBoxButton.OK); Current.Shutdown(-1); } } ,但实际上并没有成功。此外,在我的app.xaml中,我做了类似下面的操作,首先加载登录页面,然后加载实际的应用程序。

Window control

问题:如何从ViewModel关闭登录{{1}}?

提前致谢。

18 个答案:

答案 0 :(得分:124)

您可以使用CommandParameter将窗口传递给ViewModel。请参阅下面的示例。

我已经实现了一个CloseWindow方法,该方法将Windows作为参数并关闭它。该窗口通过CommandParameter传递给ViewModel。请注意,您需要为应该关闭的窗口定义x:Name。在我的XAML窗口中,我通过Command调用此方法,并使用CommandParameter将窗口本身作为参数传递给ViewModel。

Command="{Binding CloseWindowCommand, Mode=OneWay}" 
CommandParameter="{Binding ElementName=TestWindow}"

视图模型

public RelayCommand<Window> CloseWindowCommand { get; private set; }

public MainViewModel()
{
    this.CloseWindowCommand = new RelayCommand<Window>(this.CloseWindow);
}

private void CloseWindow(Window window)
{
    if (window != null)
    {
       window.Close();
    }
}

视图

<Window x:Class="ClientLibTestTool.ErrorView"
        x:Name="TestWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:localization="clr-namespace:ClientLibTestTool.ViewLanguages"
        DataContext="{Binding Main, Source={StaticResource Locator}}"
        Title="{x:Static localization:localization.HeaderErrorView}"
        Height="600" Width="800"
        ResizeMode="NoResize"
        WindowStartupLocation="CenterScreen">
    <Grid> 
        <Button Content="{x:Static localization:localization.ButtonClose}" 
                Height="30" 
                Width="100" 
                Margin="0,0,10,10" 
                IsCancel="True" 
                VerticalAlignment="Bottom" 
                HorizontalAlignment="Right" 
                Command="{Binding CloseWindowCommand, Mode=OneWay}" 
                CommandParameter="{Binding ElementName=TestWindow}"/>
    </Grid>
</Window>

请注意,我使用的是MVVM轻量级框架,但主体适用于每个wpf应用程序。

此解决方案违反了MVVM模式,因为视图模型不应该知道有关UI实现的任何信息。如果要严格遵循MVVM编程范例,则必须使用接口抽象视图类型。

MVVM符合解决方案(前EDIT2)

用户 Crono 在评论部分提及有效点:

  

将Window对象传递给视图模型会破坏MVVM模式   恕我直言,因为它迫使你的虚拟对象知道它正在被查看的内容。

您可以通过引入包含close方法的接口来解决此问题。

接口:

public interface ICloseable
{
    void Close();
}

您重构的ViewModel将如下所示:

视图模型

public RelayCommand<ICloseable> CloseWindowCommand { get; private set; }

public MainViewModel()
{
    this.CloseWindowCommand = new RelayCommand<IClosable>(this.CloseWindow);
}

private void CloseWindow(ICloseable window)
{
    if (window != null)
    {
        window.Close();
    }
}

您必须在视图中引用并实施ICloseable界面

查看(代码隐藏)

public partial class MainWindow : Window, ICloseable
{
    public MainWindow()
    {
        InitializeComponent();
    }
}

回答原始问题:(前EDIT1)

您的登录按钮(已添加CommandParameter):

<Button Name="btnLogin" IsDefault="True" Content="Login" Command="{Binding ShowLoginCommand}" CommandParameter="{Binding ElementName=LoginWindow}"/>

您的代码:

 public RelayCommand<Window> CloseWindowCommand { get; private set; } // the <Window> is important for your solution!

 public MainViewModel() 
 {
     //initialize the CloseWindowCommand. Again, mind the <Window>
     //you don't have to do this in your constructor but it is good practice, thought
     this.CloseWindowCommand = new RelayCommand<Window>(this.CloseWindow);
 }

 public bool CheckLogin(Window loginWindow) //Added loginWindow Parameter
 {
    var user = context.Users.Where(i => i.Username == this.Username).SingleOrDefault();

    if (user == null)
    {
        MessageBox.Show("Unable to Login, incorrect credentials.");
        return false;
    }
    else if (this.Username == user.Username || this.Password.ToString() == user.Password)
    {
        MessageBox.Show("Welcome "+ user.Username + ", you have successfully logged in.");
        this.CloseWindow(loginWindow); //Added call to CloseWindow Method
        return true;
    }
    else
    {
        MessageBox.Show("Unable to Login, incorrect credentials.");
        return false;
    }
 }

 //Added CloseWindow Method
 private void CloseWindow(Window window)
 {
     if (window != null)
     {
         window.Close();
     }
 }

答案 1 :(得分:26)

保留MVVM,我认为使用Blend SDK中的行为(System.Windows.Interactivity)或Prism的自定义交互请求可以很好地适应这种情况。

如果走行为路线,这是一般性的想法:

public class CloseWindowBehavior : Behavior<Window>
{
    public bool CloseTrigger
    {
        get { return (bool)GetValue(CloseTriggerProperty); }
        set { SetValue(CloseTriggerProperty, value); }
    }

    public static readonly DependencyProperty CloseTriggerProperty =
        DependencyProperty.Register("CloseTrigger", typeof(bool), typeof(CloseWindowBehavior), new PropertyMetadata(false, OnCloseTriggerChanged));

    private static void OnCloseTriggerChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var behavior = d as CloseWindowBehavior;

        if (behavior != null)
        {
            behavior.OnCloseTriggerChanged();
        }
    }

    private void OnCloseTriggerChanged()
    {
        // when closetrigger is true, close the window
        if (this.CloseTrigger)
        {
            this.AssociatedObject.Close();
        }
    }
}

然后在您的窗口中,您只需将CloseTrigger绑定到一个布尔值,该值将在您希望窗口关闭时设置。

<Window x:Class="TestApp.MainWindow"
        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:local="clr-namespace:TestApp"
        Title="MainWindow" Height="350" Width="525">
    <i:Interaction.Behaviors>
        <local:CloseWindowBehavior CloseTrigger="{Binding CloseTrigger}" />
    </i:Interaction.Behaviors>

    <Grid>

    </Grid>
</Window>

最后,您希望窗口关闭时,您的DataContext / ViewModel将具有您设置的属性:

public class MainWindowViewModel : INotifyPropertyChanged
{
    private bool closeTrigger;

    /// <summary>
    /// Gets or Sets if the main window should be closed
    /// </summary>
    public bool CloseTrigger
    {
        get { return this.closeTrigger; }
        set
        {
            this.closeTrigger = value;
            RaisePropertyChanged("CloseTrigger");
        }
    }

    public MainWindowViewModel()
    {
        // just setting for example, close the window
        CloseTrigger = true;
    }

    protected void RaisePropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

(设置你的Window.DataContext = new MainWindowViewModel())

答案 2 :(得分:25)

我通常在需要执行此操作时在视图模型上放置一个事件,然后在将视图模型绑定到窗口时将其挂钩到Window.Close()

public class LoginViewModel
{
    public event EventHandler OnRequestClose;

    private void Login()
    {
        // Login logic here
        OnRequestClose(this, new EventArgs());
    }
}

创建登录窗口时

var vm = new LoginViewModel();
var loginWindow = new LoginWindow
{
    DataContext = vm
};
vm.OnRequestClose += (s, e) => loginWindow.Close();

loginWindow.ShowDialog(); 

答案 3 :(得分:12)

这是我在几个项目中使用的东西。它可能看起来像一个黑客,但它工作正常。

public class AttachedProperties : DependencyObject //adds a bindable DialogResult to window
{
    public static readonly DependencyProperty DialogResultProperty = 
        DependencyProperty.RegisterAttached("DialogResult", typeof(bool?), typeof(AttachedProperties), 
        new PropertyMetaData(default(bool?), OnDialogResultChanged));

    public bool? DialogResult
    {
        get { return (bool?)GetValue(DialogResultProperty); }
        set { SetValue(DialogResultProperty, value); }
    }

    private static void OnDialogResultChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var window = d as Window;
        if (window == null)
            return;

        window.DialogResult = (bool?)e.NewValue;
    }
}

现在,您可以将DialogResult绑定到VM并设置其属性值。设置值后,Window将关闭。

<!-- Assuming that the VM is bound to the DataContext and the bound VM has a property DialogResult -->
<Window someNs:AttachedProperties.DialogResult={Binding DialogResult} />

这是我们生产环境中正在运行的内容的摘要

<Window x:Class="AC.Frontend.Controls.DialogControl.Dialog"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:DialogControl="clr-namespace:AC.Frontend.Controls.DialogControl" 
        xmlns:hlp="clr-namespace:AC.Frontend.Helper"
        MinHeight="150" MinWidth="300" ResizeMode="NoResize" SizeToContent="WidthAndHeight"
        WindowStartupLocation="CenterScreen" Title="{Binding Title}"
        hlp:AttachedProperties.DialogResult="{Binding DialogResult}" WindowStyle="ToolWindow" ShowInTaskbar="True"
        Language="{Binding UiCulture, Source={StaticResource Strings}}">
        <!-- A lot more stuff here -->
</Window>

如您所见,我首先声明命名空间xmlns:hlp="clr-namespace:AC.Frontend.Helper",然后声明绑定hlp:AttachedProperties.DialogResult="{Binding DialogResult}"

AttachedProperty看起来像这样。这与我昨天发布的不一样,但恕我直言,它应该没有任何效果。

public class AttachedProperties
{
    #region DialogResult

    public static readonly DependencyProperty DialogResultProperty =
        DependencyProperty.RegisterAttached("DialogResult", typeof (bool?), typeof (AttachedProperties), new PropertyMetadata(default(bool?), OnDialogResultChanged));

    private static void OnDialogResultChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var wnd = d as Window;
        if (wnd == null)
            return;

        wnd.DialogResult = (bool?) e.NewValue;
    }

    public static bool? GetDialogResult(DependencyObject dp)
    {
        if (dp == null) throw new ArgumentNullException("dp");

        return (bool?)dp.GetValue(DialogResultProperty);
    }

    public static void SetDialogResult(DependencyObject dp, object value)
    {
        if (dp == null) throw new ArgumentNullException("dp");

        dp.SetValue(DialogResultProperty, value);
    }

    #endregion
}

答案 4 :(得分:10)

简单方法

public interface IRequireViewIdentification
{
    Guid ViewID { get; }
}

实施到ViewModel

public class MyViewVM : IRequireViewIdentification
{
    private Guid _viewId;

    public Guid ViewID
    {
        get { return _viewId; }
    }

    public MyViewVM()
    {
        _viewId = Guid.NewGuid();
    }
}

添加常规窗口管理器帮助程序

public static class WindowManager
{
    public static void CloseWindow(Guid id)
    {
        foreach (Window window in Application.Current.Windows)
        {
            var w_id = window.DataContext as IRequireViewIdentification;
            if (w_id != null && w_id.ViewID.Equals(id))
            {
                window.Close();
            }
        }
    }
}

在viewmodel

中将其关闭
WindowManager.CloseWindow(ViewID);

答案 5 :(得分:9)

可能会迟到,但这是我的回答

abbr

答案 6 :(得分:4)

this怎么样?

视图模型:

class ViewModel
{
    public Action CloseAction { get; set; }
    private void Stuff()
    {
       // Do Stuff
       CloseAction(); // closes the window
    }
}

在ViewModel中使用CloseAction()来关闭窗口,就像上面的示例一样。

查看:

public View()
{
    InitializeComponent();
    ViewModel vm = new ViewModel (); // this creates an instance of the ViewModel
    this.DataContext = vm; // this sets the newly created ViewModel as the DataContext for the View
    if (vm.CloseAction == null)
        vm.CloseAction = new Action(() => this.Close());
}

答案 7 :(得分:3)

这是我非常简单的方式:

<强> YourWindow.xaml.cs

//In your constructor
public YourWindow()
{
    InitializeComponent();
    DataContext = new YourWindowViewModel(this);
}

<强> YourWindowViewModel.cs

private YourWindow window;//so we can kill the window

//In your constructor
public YourWindowViewModel(YourWindow window)
{
    this.window = window;
}

//to close the window
public void CloseWindow()
{
    window.Close();
}

我没有看到你选择的答案有什么问题,我只是觉得这可能是一种更简单的方法!

答案 8 :(得分:2)

这是一个使用MVVM Light Messenger而不是事件的简单示例。单击按钮时,视图模型会发送关闭消息:

    public MainViewModel()
    {
        QuitCommand = new RelayCommand(ExecuteQuitCommand);
    }

    public RelayCommand QuitCommand { get; private set; }

    private void ExecuteQuitCommand() 
    {
        Messenger.Default.Send<CloseMessage>(new CloseMessage());
    }

然后在窗口后面的代码中收到它。

    public Main()
    {   
        InitializeComponent();
        Messenger.Default.Register<CloseMessage>(this, HandleCloseMessage);
    }

    private void HandleCloseMessage(CloseMessage closeMessage)
    {
        Close();
    }

答案 9 :(得分:1)

您可以像这样在ViewModel中创建新的事件处理程序。

$i=0;
while($row = $result->fetch_array(MYSQLI_BOTH) and ($counter < $max)){
  $url=$row['url'];
  $class = ($i%2 == 0) ? 'first' : 'second';
  echo "<img src='$url' class='$class'>";
  ++$i;
}

然后为ExitCommand定义RelayCommand。

public event EventHandler RequestClose;

    protected void OnRequestClose()
    {
        if (RequestClose != null)
            RequestClose(this, EventArgs.Empty);
    }

然后在XAML文件集中

private RelayCommand _CloseCommand;
    public ICommand CloseCommand
    {
        get
        {
            if(this._CloseCommand==null)
                this._CloseCommand=new RelayCommand(CloseClick);
            return this._CloseCommand;
        }
    }

    private void CloseClick(object obj)
    {
        OnRequestClose();
    }

在xaml.cs文件中设置DataContext并订阅我们创建的事件。

<Button Command="{Binding CloseCommand}" />

答案 10 :(得分:1)

我提供的方法是在ViewModel中声明事件并使用如下的混合InvokeMethodAction。

示例ViewModel

public class MainWindowViewModel : BindableBase, ICloseable
{
    public DelegateCommand SomeCommand { get; private set; }
    #region ICloseable Implementation
    public event EventHandler CloseRequested;        

    public void RaiseCloseNotification()
    {
        var handler = CloseRequested;
        if (handler != null)
        {
            handler.Invoke(this, EventArgs.Empty);
        }
    }
    #endregion

    public MainWindowViewModel()
    {
        SomeCommand = new DelegateCommand(() =>
        {
            //when you decide to close window
            RaiseCloseNotification();
        });
    }
}

I Closeable界面如下所示,但不需要执行此操作。 ICloseable将有助于创建通用视图服务,因此如果您通过依赖注入构造视图和ViewModel,那么您可以做的是

internal interface ICloseable
{
    event EventHandler CloseRequested;
}

使用ICloseable

var viewModel = new MainWindowViewModel();
        // As service is generic and don't know whether it can request close event
        var window = new Window() { Content = new MainView() };
        var closeable = viewModel as ICloseable;
        if (closeable != null)
        {
            closeable.CloseRequested += (s, e) => window.Close();
        }

以下是Xaml,即使您没有实现界面,也可以使用此xaml,它只需要您的视图模型来提升CloseRquested。

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WPFRx"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" 
xmlns:ViewModels="clr-namespace:WPFRx.ViewModels" x:Name="window" x:Class="WPFRx.MainWindow"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525" 
d:DataContext="{d:DesignInstance {x:Type ViewModels:MainWindowViewModel}}">

<i:Interaction.Triggers>
    <i:EventTrigger SourceObject="{Binding Mode=OneWay}" EventName="CloseRequested" >
        <ei:CallMethodAction TargetObject="{Binding ElementName=window}" MethodName="Close"/>
    </i:EventTrigger>
</i:Interaction.Triggers>

<Grid>
    <Button Content="Some Content" Command="{Binding SomeCommand}" Width="100" Height="25"/>
</Grid>

答案 11 :(得分:1)

您可以使用MVVMLight工具包中的Messenger。在ViewModel发送如下信息:
Messenger.Default.Send(new NotificationMessage("Close"));
  然后在你的Windows代码后面InitializeComponent之后,注册这样的消息:

Messenger.Default.Register<NotificationMessage>(this, m=>{
    if(m.Notification == "Close") 
    {
        this.Close();
    }
   });

您可以在此处找到有关MVVMLight工具包的更多信息: MVVMLight toolkit on Codeplex

请注意,在所有规则中都没有&#34;没有代码隐藏&#34;在MVVM中,您可以在代码隐藏视图中注册消息。

答案 12 :(得分:0)

在 MVVM WPF 中,我通常将视图设计为 UserControl。这只是你想如何显示它的问题。如果你想让它在一个窗口中,那么你可以做一个 WindowService 类:

public class WindowService
{
   //...

   public void Show_window(object viewModel, int height, int width, string title)
   {
     var window = new Window
     {
       Content = viewModel,
       Title = title,
       Height = height,
       Width = width,
       WindowStartupLocation = WindowStartupLocation.CenterOwner,
       Owner = Application.Current.MainWindow,
       Style = (Style)Application.Current.FindResource("Window_style") //even style can be added
      };

      //If you own custom window style, then you can bind close/minimize/maxmize/restore buttons like this 
      window.CommandBindings.Add(new CommandBinding(SystemCommands.CloseWindowCommand, OnCloseWindow));
      window.CommandBindings.Add(new CommandBinding(SystemCommands.MaximizeWindowCommand, OnMaximizeWindow, OnCanResizeWindow));
      window.CommandBindings.Add(new CommandBinding(SystemCommands.MinimizeWindowCommand, OnMinimizeWindow, OnCanMinimizeWindow));
      window.CommandBindings.Add(new CommandBinding(SystemCommands.RestoreWindowCommand, OnRestoreWindow, OnCanResizeWindow));
                  
      window.ShowDialog();
   }

   public void Close_window(object viewmodel)
   {
       //Close window
       foreach (Window item in Application.Current.Windows)
       {
          if (item.Content == viewmodel) item.Close();
       }
    }
}

使用我的方法很简单。通常你想在它发生某些事情时关闭 Window。因此,当它这样做时,只需从相应的 ViewModel 调用 Close_window 方法 - 这是显示在窗口中的 UserControl 的 DataContext 。看底部示例:

1.) 我们从一些 Viewmodel 打开 Window:

public class MyViewModel // ViewModel where you open window
{
   private readonly WindowService _windowservice // or inject/inherit from Base

   public MyViewModel()
   {
     _windowservice = new WindowService();
   }  

   private void Example_method()
   {
        //...Open window
        _windowservice.Show_window(new WindowViewModel(),100,100,"Test window");
   }
  
}

2.) 我们的窗口已经打开,现在我们要关闭它:

 public class WindowViewModel // ViewModel which is your Window content!
 {
     private readonly WindowService _windowservice // or inject/inherit from Base

     public MyViewModel()
     {
       _windowservice = new WindowService();
     }  

     private void Example_method()
     {
          //Close window
          _windowservice.Close(this); //Pass a reference of viewmodel to method
     }
    
  }

这个解决方案远没有其他公认的答案那么优雅,但对我来说它有效。我在项目中广泛使用它,到目前为止它没有问题。但我敢肯定有人会过来说“这违反了 MVVM 原则”。

答案 13 :(得分:0)

您可以将窗口视为服务(例如UI服务),然后通过界面将其自身传递给视图模型,例如:

public interface IMainWindowAccess
{
    void Close(bool result);
}

public class MainWindow : IMainWindowAccess
{
    // (...)
    public void Close(bool result)
    {
        DialogResult = result;
        Close();
    }
}

public class MainWindowViewModel
{
    private IMainWindowAccess access;

    public MainWindowViewModel(IMainWindowAccess access)
    {
        this.access = access;
    }

    public void DoClose()
    {
        access.Close(true);
    }
}

此解决方案具有将视图本身传递给viewmodel的最大优势,而不会破坏MVVM,因为尽管物理视图传递给viewmodel,但后者仍然不了解前者,它只能看到一些{{1} }。因此,例如,如果我们想将此解决方案迁移到其他平台,则仅是为IMainWindowAccess正确实施IMainWindowAccess的问题。

我在这里发布解决方案以提出一种不同于事件的方法(尽管实际上非常相似),因为它似乎比实现事件(附加/分离等)要简单一些,但是仍然与MVVM保持一致模式。

答案 14 :(得分:0)

我知道这是一篇过时的文章,可能没有人会滚动到这么远,我知道我没有。因此,经过数小时的尝试,我找到了这个博客,并把它杀死了。进行此操作的最简单方法是尝试一下,它就像一种魅力。

Blog

答案 15 :(得分:0)

您只需使用以下代码关闭当前窗口:

Application.Current.Windows[0].Close();

答案 16 :(得分:0)

这很简单。 您可以为Login创建自己的ViewModel类 - LoginViewModel。 您可以创建view var dialog = new UserView();在您的LoginViewModel中。 您可以将Command LoginCommand设置为按钮。

<Button Name="btnLogin" IsDefault="True" Content="Login" Command="{Binding LoginCommand}" />

<Button Name="btnCancel" IsDefault="True" Content="Login" Command="{Binding CancelCommand}" />

ViewModel类:

public class LoginViewModel
{
    Window dialog;
    public bool ShowLogin()
    {
       dialog = new UserView();
       dialog.DataContext = this; // set up ViewModel into View
       if (dialog.ShowDialog() == true)
       {
         return true;
       }

       return false;
    }

    ICommand _loginCommand
    public ICommand LoginCommand
    {
        get
        {
            if (_loginCommand == null)
                _loginCommand = new RelayCommand(param => this.Login());

            return _loginCommand;
        }
    }

    public void CloseLoginView()
    {
            if (dialog != null)
          dialog.Close();
    }   

    public void Login()
    {
        if(CheckLogin()==true)
        {
            CloseLoginView();         
        }
        else
        {
          // write error message
        }
    }

    public bool CheckLogin()
    {
      // ... check login code
      return true;
    }
}

答案 17 :(得分:-4)

System.Environment.Exit(0);在视图模型中可以工作。