1 易用性細節優化
1.1 程式碼片段
在ViewModel內,會有大量重複性的在Property set中激發 INotifyPropertyChanged.PropertyChanged 事件的程式碼。 這種屬性用已有的程式碼片段已經很難高效的輸入。使用合適的程式碼片段在VM設計時 不會因為過於機械的修改影響設計思路
1.1.1 Property Code Snippets
在專案模板中加入對應的code snippet
Sample:
鍵入 propvm [Tab] [Tab]後 產生如下程式碼
private int _PropertyName; public int PropertyName {
get { return _PropertyName; } set { _PropertyName=value; RaisePropertyChanged(()=>PropertyName); } }
1.1.2 Command Code Snippets
同樣作為Command<Object> 的屬性 也需要類似的code snippets
Sample:
鍵入 propcmd[Tab] [Tab]後 產生如下程式碼
private Command<Object> _CommandName= new Command<Object> ( p=>{}, p=>true); public Command< Object > CommandName { get { return _CommandName; } set { _CommandName =value; RaisePropertyChanged(()=>CommandName); } }
1.2 設計時支援
作為MVVM的UI開發設計基礎,一個生產力足夠高的框架應當能夠為設計時提供VM的結構成員和設計時資料支援。
1.2.1 步驟:在設計檢視新增設計時VM.
假設我們有一個ViewModel 型別為 My.Project.TestViewModel
在設計器正確引入如下名稱空間時
<UserControl … </UserControl>
|
在設計器根節點加入
<d:FrameworkElement.DataContext> </d:FrameworkElement.DataContext>
|
這時設計器會為View指定一個TestViewModel的新例項,此時繫結會用這個新例項為模板進行設計時支援,比如所見即所得的繫結結果顯示,以及模板設計支援。
對於早期版本的 VS,或者WPF/SL 以外不能支援 blend設計時名稱空間的平臺,d:DataContext 不被設計時支援, 這時候我們可能需要直接使用 <FrameworkElement.DataContext> 標記。這樣做的代價可能是額外產生一個 ViewModel 物件引用。 如果我們能夠控制好 ViewModel 預設建構函式中呼叫的資源,這樣做問題並不大,不失為一種辦法。
1.2.2 步驟:在VM新增設計時資料與邏輯
由於設計時設計器會建立一個VM例項來幫助設計,VM的設計需要注意以下幾點
l VM要具有預設建構函式,否則設計器無法將其例項化
l VM中的邏輯要能夠判斷當前執行環境是否在設計時
n 使用大量珍貴資源的邏輯在設計時不允許執行,比如
u Timer 邏輯
u IO操作
應當在適當位置新增 “IsInDesignMode” 靜態屬性,建議在 ViewModelBase中新增。
static bool? _IsInDesignMode; /// <summary> /// <para>Gets if the code is running in design time. </para> /// <para>讀取目前是否在設計時狀態。</para> /// </summary> public static bool IsInDesignMode { get { return ( _IsInDesignMode ?? ( _IsInDesignMode = #if SILVERLIGHT_5||WINDOWS_PHONE_8||WINDOWS_PHONE_7 DesignerProperties.IsInDesignTool #elif NETFX_CORE Windows.ApplicationModel.DesignMode.DesignModeEnabled #else (bool)System.ComponentModel.DependencyPropertyDescriptor .FromProperty( DesignerProperties.IsInDesignModeProperty,
typeof(System.Windows.FrameworkElement)) .Metadata .DefaultValue #endif )) .Value; } }
在實現了這個屬性之後 在具體Vm的建構函式或Onload事件中使用者就可以新增偽資料,也可以避免不能再設計時呼叫的功能被呼叫
比如下面這段程式碼
protected override async Task OnBindedViewLoad(MVVMSidekick.Views.IView view) { await base.OnBindedViewLoad(view); if (IsInDesignMode) { HelloWorld = "Hello Mvvm world, Design mode sample"; } else { if (Id == null) { Id = Guid.NewGuid().ToString(); } GetValueContainer(x => x.CountDown).GetNullObservable() .Subscribe( _ => { HelloWorld = string.Format("Loading {0}", CountDown); } ); } }
當然, MVVM-Sidekick 這些方面做的都很不錯。