矯枉過正,從一個極端走向另一個極端。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,反而失去了控制失效使能的作用,有時會不友善。