1. 程式人生 > >WPF學習筆記:MVVM模式下,ViewModel如何關閉View?

WPF學習筆記:MVVM模式下,ViewModel如何關閉View?

矯枉過正,從一個極端走向另一個極端。MVVM模式,View只負責呈現,雖然也有後臺程式碼,但基本上就是擺設,VM接管了一切的邏輯處理。

那麼,現在,大能的VM已經完成了所有的事情,這個視窗V如何才能自動關閉呢?

據我目前少得可憐的WPF知識可知,有兩種方案:

一、利用View裡的IsEnable屬性

原理是這樣的:

1、UI中的IsEnabled繫結VM中的屬性

2、UI的後臺程式碼中,註冊IsEnableChange事件,在這個事件裡,檢測到傳過來的值滿足某個條件,即可觸發Close()命令

如此,VM控制自己那個屬性就能達到關閉V的目的了。

沒程式碼我說個J8:

UI

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	……
    IsEnabled="{Binding IsLoginFailed, Mode=OneWay}">
UI後臺程式碼
        public LoginWindow()
        {
            InitializeComponent();

            this.IsEnabledChanged += LoginWindow_IsEnabledChanged;
        }
        private void LoginWindow_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            if ((bool)e.NewValue == false)
            {
                this.Close();
            }
        }
VM
        private bool isLoginFailed = true;
        /// <summary>
        /// <para>獲取或設定一個表示是否登入失敗的值;true表示登入失敗,否則為false。</para>
        /// <para>與LoginWindow的IsEnable屬性繫結。當為False時,關閉Login Window。</para>
        /// 當該屬性更改時通知客戶端。 
        /// </summary>
        public bool IsLoginFailed
        {
            get
            {
                return this.isLoginFailed;
            }

            set
            {
                if (this.isLoginFailed != value)
                {
                    this.isLoginFailed = value;
                    this.RaisePropertyChanged("IsLoginFailed");
                }
            }
        }


二、用Invoke

1、UI後臺程式碼:

        public LoginWindow()
        {
            InitializeComponent();

            this.DataContext = new LoginWindowVM(this.Close);
        }

2、VM程式碼:
        Action _closeAction;
        public LoginWindowVM(Action closeAction)
        {
            InitializeLoginInfo();
            this._closeAction = closeAction;
        }
        void CloseWin()
        {
            App.Current.Dispatcher.Invoke((Action)(() =>
            {
                this._closeAction.Invoke();
            }));
        }

兩種方法,無疑第一種比較符合MVVM的思想。VM發出關閉的訊號,觸發V進行關閉,如何關閉,何時關閉,都由V自己控制;

而方案二,通過呼叫的方式來直接進行關閉,好像有點越俎代庖?

但是,IsEnable本意是用來控制失效和使能的,卻被用於關閉UI,反而失去了控制失效使能的作用,有時會不方便。

方案二參考文章: