WPF MVVM从入门到精通7:关闭窗口和打开新窗口

若是登录成功,我们一般会执行的操作是关闭当前窗口,然后打开一个新的窗口。但为了比较理想地实现MVVM,我们被禁止在ViewModel里面访问View的元素。那我们该如何实现上面的功能呢?

首先是打开窗口的功能,我们使用的方法是:

(1)窗口初始化的时候即注册需要访问的新窗口。

(2)ViewModel在需要打开新窗口时,使用注册过的窗口。

我们先定义一个WindowManager类:

    using System;
    using System.Collections;
    using System.Windows;
     
    namespace LoginDemo.ViewModel.Common
    {
        /// <summary>
        /// 窗口管理器
        /// </summary>
        public static class WindowManager
        {
            private static Hashtable _RegisterWindow = new Hashtable();
     
            public static void Register<T>(string key)
            {
                if (!_RegisterWindow.Contains(key))
                {
                    _RegisterWindow.Add(key, typeof(T));
                }
            }
     
            public static void Register(string key, Type t)
            {
                if (!_RegisterWindow.Contains(key))
                {
                    _RegisterWindow.Add(key, t);
                }
            }
     
            public static void Remove(string key)
            {
                if (_RegisterWindow.ContainsKey(key))
                {
                    _RegisterWindow.Remove(key);
                }
            }
     
            public static void Show(string key, object VM)
            {
                if (_RegisterWindow.ContainsKey(key))
                {
                    var win = (Window)Activator.CreateInstance((Type)_RegisterWindow[key]);
                    win.DataContext = VM;
                    win.Show();
                }
            }
        }
    }

代码比较简单,就不解释了。然后我们在LoginWindow的构造函数里添加代码,变成如下所示:

    using LoginDemo.ViewModel.Common;
    using LoginDemo.ViewModel.Login;
    using System.Windows;
     
    namespace LoginDemo
    {
        /// <summary>
        /// LoginWindow.xaml 的交互逻辑
        /// </summary>
        public partial class LoginWindow : Window
        {
            public LoginWindow()
            {
                InitializeComponent();
     
                this.DataContext = new LoginViewModel();
     
                WindowManager.Register<MainWindow>("MainWindow");
            }
        }
    }

是不是发现这里说好只加一行,现在又加一行代码了?实在没有办法,打开窗口就是要这么做。

然后我们在ViewModel需要打开窗口的地方写下面一行代码:

WindowManager.Show("MainWindow", null);

这样新的窗口就能在ViewModel里面被打开了。

 

我们接下来说关闭窗口。要做到这一功能,我们又要借助System.Windows.Interacivity里面的Behavior。它可以把ViewModel里面的一个属性,关联到View层的一个事件(我们这里当然是要关联Window.Close())。

我们先来定义这个关闭行为:

    using System.Windows;
    using System.Windows.Interactivity;
     
    namespace LoginDemo.ViewModel.Common
    {
        /// <summary>
        /// 窗口行为
        /// </summary>
        public class WindowBehavior : Behavior<Window>
        {
            /// <summary>
            /// 关闭窗口
            /// </summary>
            public bool Close
            {
                get { return (bool)GetValue(CloseProperty); }
                set { SetValue(CloseProperty, value); }
            }
            public static readonly DependencyProperty CloseProperty =
                DependencyProperty.Register("Close", typeof(bool), typeof(WindowBehavior), new PropertyMetadata(false, OnCloseChanged));
            private static void OnCloseChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                var window = ((WindowBehavior)d).AssociatedObject;
                var newValue = (bool)e.NewValue;
                if (newValue)
                {
                    window.Close();
                }
            }
     
        }
    }

然后我们在XAML文件里增加以下内容:

    <i:Interaction.Behaviors>
        <c:WindowBehavior Close="{Binding ToClose}"/>
    </i:Interaction.Behaviors>

这样的话,窗口的关闭事件就绑定到了ViewModel里面的ToClose属性了。但这个属性还没有呢,定义一个:

    private bool toClose = false;
    /// <summary>
    /// 是否要关闭窗口
    /// </summary>
    public bool ToClose
    {
        get
        {
            return toClose;
        }
        set
        {
            toClose = value;
            if (toClose)
            {
                this.RaisePropertyChanged("ToClose");
            }
        }
    }

如此,只要我们在ViewModel里面执行ToClose=true;,当前窗口就会关闭。这节的内容体现在点击登录按钮上,大体如下:

    private BaseCommand loginClick;
    /// <summary>
    /// 登录事件
    /// </summary>
    public BaseCommand LoginClick
    {
        get
        {
            if (loginClick == null)
            {
                loginClick = new BaseCommand(new Action<object>(o =>
                {
                    //执行登录逻辑
                    WindowManager.Show("MainWindow", null);
                    ToClose = true;
                }));
            }
            return loginClick;
        }
    }

WPF MVVM从入门到精通7:关闭窗口和打开新窗口

上一篇:窗体进行自动适应窗口


下一篇:cocos creator发布win10全屏缩放问题