【乾貨】個人工作文件節選:XAML MVVM 框架易用性細節優化Tips

MSFT:waywa 韋恩卑鄙發表於2013-12-06

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
    xmlns:d=”http://schemas.microsoft.com/expression/blend/2008”
    xmlns:vm=”clr-namespace:My.Project”
    …>

   

   

</UserControl>

   

 

   
   

 

在設計器根節點加入

             

   
   

<d:FrameworkElement.DataContext>
        <vm:TestViewModel />

   

</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 這些方面做的都很不錯。

相關文章