C# WPF MVVM模式下第二个窗口激活时如何关闭第一个登录窗口
问题原因
- 你代码中实例化了新的
MainWindow对象调用Close,操作的不是当前已经打开的登录窗口实例,自然无法关闭原有窗口 nw.IsActive的判断逻辑多余,刚调用Show()的窗口不会立刻激活,这个判断大概率不会触发
修复方案
方案1:快速实现(不破坏现有代码结构)
直接从应用程序的窗口集合中获取已经打开的登录窗口实例进行关闭,修改后的Login方法代码如下:
// 需要先引入Linq命名空间:using System.Linq; private void Login() { if (Username == "student" && Password == "password") { AppMainWindow nw = new AppMainWindow(); nw.Show(); // 查找当前已打开的MainWindow实例关闭 var loginWindow = Application.Current.Windows.OfType<MainWindow>().FirstOrDefault(); loginWindow?.Close(); } else { MessageBox.Show("Username or password is incorrect!"); } }
方案2:符合MVVM规范的实现(推荐)
ViewModel不应该直接操作View层的窗口对象,你可以通过事件通知的方式解耦:
- 首先在LoginViewModel中定义登录成功的事件
public class LoginViewModel : ViewModelBase { // 新增登录成功事件 public event EventHandler LoginSucceeded; // 其他原有属性、构造函数保持不变 private void Login() { if (Username == "student" && Password == "password") { // 触发登录成功事件,不直接操作窗口 LoginSucceeded?.Invoke(this, EventArgs.Empty); } else { MessageBox.Show("Username or password is incorrect!"); } } }
- 在MainWindow的后台代码中订阅这个事件,在事件触发时打开新窗口关闭自身
// MainWindow.xaml.cs构造函数 public MainWindow() { InitializeComponent(); var vm = new LoginViewModel(); this.DataContext = vm; // 订阅登录成功事件 vm.LoginSucceeded += (s, e) => { AppMainWindow nw = new AppMainWindow(); nw.Show(); this.Close(); }; }
这种方式完全符合MVVM的职责分离原则,ViewModel只负责业务逻辑,窗口的创建关闭都由View层处理,不会出现跨层调用的问题。
内容的提问来源于stack exchange,提问作者AlaSwek
相关产品推荐
相关产品推荐

