基于以下的理由,ViewModel也是需要多個,并且需要被注入的:
1:設計時和運作時需要為View提供不同的資料
簡單來說,就是設計時需要模拟資料。界面設計開發人員需要進行綁定(包括支援Expression Blend綁定)做一些簡單的處理,同時因為提供了模拟資料,UI人員可以更好的設計實際的界面。
2:為了友善單元測試
在運作時,大部分情況下,ViewModel會組合進提供Service的業務類。在簡單的應用中,我們可以注入Service類的MOCK來進行單元測試,如果是這樣,就可以避免提供多個ViewModel。但在有些應用中,如Silverlight應用中,服務由WerbService、WCF提供,就無法讓用戶端應用服務所支援的接口類,并且用戶端的代碼都是自動生成的,這樣我們就需要提供多個ViewModel來支援單元測試。
3:為設計時提供模拟資料
考慮到VM需要存在多個,是以UI的VM需要存在一個基類,假設我的UI需要顯示一個學生的清單,那麼我的VM基類設計如下:
public class MainPageVmBase
{
public MainPageVmBase()
{
click = new DelegateCommand(OnClick);
}
public IStudent StudentService { get; set; }
public IView View { get; set; }
private ICommand click;
public ICommand Click
{
get { return click; }
set { click = value; }
}
void OnClick(object arg)
{
View.Title = arg as string;
View.Show();
}
private List<Student> studets;
public List<Student> Studets
{
get { return studets; }
set { studets = value; }
}
}
設計時的VM需要提供模拟資料,那麼該VM為:
public class MainPageVmMock : MainPageVmBase
{
public MainPageVmMock()
{
Studets = new List<Student>()
{
new Student() {Name = "d1", Age = 11},
new Student() {Name = "d2", Age = 22}
};
}
}
要讓設計時顯式模拟資料,我們需要用到一個DesignHelpers類(該類來自于
https://github.com/jeremiahredekop/):
public static class DesignHelpers
{
private static bool? _designMode;
public static bool DesignMode
{
get
{
if (!_designMode.HasValue)
{
#if !SILVERLIGHT
_designMode = new bool?(DesignerProperties.GetIsInDesignMode(new System.Windows.DependencyObject()));
#else
_isInDesignMode = new bool?(DesignerProperties.IsInDesignTool);
#endif
}
return _designMode.Value;
}
}
}
借助于這個類的處理,這個時候我們在Expression Blend進行綁定的時候,就可以顯式我們的模拟資料:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIn5GcuQzNmRDMhJzMwUGNidTMhNDO3QTO2kjMjRTZmNGNmBTMfdWbp9CXt92Yu4GZjlGbh5SZslmZxl3Lc9CX6MHc0RHaiojIsJye.png)
4:ViewModel FACTORY
每個UI綁定的VM實際都來自于VM FACTORY的類,如上面這個頁面,我們綁定的就是MainPageVmFactory中的ViewModel屬性。每個VmFactory也有自己的基類,如下:
public class ViewModelFactory<TViewModelRealBase>
where TViewModelRealBase : class, new()
{
public TViewModelRealBase ViewModel
{
get;
set;
}
}
MainPageVmFactory如下:
public class MainPageVmFactory : ViewModelFactory<MainPageVmBase>
{
public MainPageVmFactory()
{
if (DesignHelpers.DesignMode == true)
{
this.ViewModel = new MainPageVmMock();
}
else
{
using (IUnityContainer container = new UnityContainer())
{
var section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
section.Configure(container, "containerOne");
this.ViewModel = container.Resolve<MainPageVmBase>("MainPageVmReal");
}
}
}
}
可以看到,運作時的VM我們通過unity注入的方式來得到,本文一開頭已經說過了,之是以采用注入方式是為了單元測試友善。注入的是MainPageVmReal這個類型,它包含有實際提供資料的服務類,如下:
public class MainPageVmReal : MainPageVmBase
{
public MainPageVmReal()
{
//Studets = new List<Student>()
// {
// new Student() {Name = "r1", Age = 11},
// new Student() {Name = "r2", Age = 22}
// };
using (IUnityContainer container = new UnityContainer())
{
UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
section.Configure(container, "containerOne");
IStudent service = container.Resolve<IStudent>("StudentService");
Studets = service.GetAllStudent() as List<Student>;
}
}
}
MainPageVmReal中實際提供資料的服務類,可以是WCF的用戶端代碼,或者是任何别的東西,這裡不是我們關注的重點,是以我們可以不用去管裡面的那段注入代碼。
運作時結果:
5:關于注入
注入這部分就很容易了解了,在配置處寫入我們實際需要VM類型就可以了:
整體代碼下載下傳:
WpfApplication20110811.rar本文基于
Creative Commons Attribution 2.5 China Mainland License釋出,歡迎轉載,演繹或用于商業目的,但是必須保留本文的署名
http://www.cnblogs.com/luminji(包含連結)。如您有任何疑問或者授權方面的協商,請給我留言。