在MVVM設計中,如果遇到界面打開時需要讀取數據庫數據,此爲耗時操作,我又有潔癖,不想把這段代碼寫到ViewMoel的構造函數中。
於是便有了下面的解決方案!
靈感來源與設計模式中的橋接模式,使得界面的ViewModel和Control的ViewModel獨立變化
首先是在項目中此次用到的控件功能,只有加載和卸載的功能,加載時提供數據,卸載時清理數據。
設計接口的UML如下:
3個屬性,2個事件,MVVM模式中,View和ViewModel的數據交換主要是靠Bingding,而交互主要是靠 命令 Command,所以在此接口中設計了加載命令和LoadedCommand和卸載命令UnloadedCommand,以及這兩個命令執行時所觸發的事件Loaded和Unloaded。接口代碼實現如下:
/// <summary>
/// The ControlViewModel interface.
/// </summary>
public interface IControlViewModel
{
/// <summary>
/// The loaded event.
/// </summary>
event EventHandler Loaded;
/// <summary>
/// The unloaded event.
/// </summary>
event EventHandler Unloaded;
/// <summary>
/// Gets the loaded command.
/// </summary>
ICommand LoadedCommand { get; }
/// <summary>
/// Gets the unloaded command.
/// </summary>
ICommand UnloadedCommand { get; }
/// <summary>
/// Gets or sets the title.
/// </summary>
string Title { get; set; }
}
ControlViewModel 爲IControlViewModel結構實現類,繼承自ViewModelBase(注1),實現代碼如下:
/// <summary>
/// The control view model.
/// </summary>
public class ControlViewModel : ViewModelBase, IControlViewModel
{
#region Fields
/// <summary>
/// The title.
/// </summary>
private string title;
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="ControlViewModel"/> class.
/// </summary>
public ControlViewModel()
{
this.LoadedCommand = new RelayCommand(this.OnLoaded);
this.UnloadedCommand = new RelayCommand(this.OnUnloaded);
}
#endregion
#region Events
/// <summary>
/// The loaded.
/// </summary>
public event EventHandler Loaded;
/// <summary>
/// The unloaded.
/// </summary>
public event EventHandler Unloaded;
#endregion
#region Commands
/// <summary>
/// Gets the loaded command.
/// </summary>
public ICommand LoadedCommand { get; private set; }
/// <summary>
/// Gets the unloaded command.
/// </summary>
public ICommand UnloadedCommand { get; private set; }
#endregion
#region Properteis
/// <summary>
/// Gets or sets the title.
/// </summary>
public string Title
{
get
{
return this.title;
}
set
{
this.title = value;
this.RaisePropertyChanged("Title");
}
}
#endregion
#region Methods
/// <summary>
/// The on loaded.
/// </summary>
private void OnLoaded()
{
var loaded = this.Loaded;
if (loaded != null)
{
loaded(this, new EventArgs());
}
}
/// <summary>
/// The on unloaded.
/// </summary>
private void OnUnloaded()
{
var unloaded = this.Unloaded;
if (unloaded != null)
{
unloaded(this, new EventArgs());
}
}
#endregion
}
可以清楚的看到在構造函數中初始化兩個命令的時候,這兩個命令分別觸發了加載Loaded和卸載Unloaded的事件.
那麼,它們是怎麼工作的呢?如何當頁面加載的時候就去執行LoadedCommand命令呢?請繼續往下看:
首先,我們要在界面的項目工程中引入 System.Windows.Interactivity.dll 程序集。
然後,在界面中,添加如下代碼:
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<i:InvokeCommandAction
Command="{Binding ControlViewModel.LoadedCommand}">
</i:InvokeCommandAction>
</i:EventTrigger>
<i:EventTrigger EventName="Unloaded">
<i:InvokeCommandAction
Command="{Binding ControlViewModel.UnloadedCommand}">
</i:InvokeCommandAction>
</i:EventTrigger>
</i:Interaction.Triggers>
通過觸發器將事件綁定到命令,當Loaded事件加載時,會執行ControlViewModel屬性的LoadedCommand命令,當Unloaded事件被觸發時,會執行ControlViewModel屬性的UnloadedCommand命令。
界面的ViewModel代碼如下:
public class MainViewModel: ViewModelBase
{
/// <summary>
/// Initializes a new instance of the <see cref="InstrumentCorrectVm"/> class.
/// </summary>
public MainViewModel()
{
this.ControlViewModel = new ControlViewModel();
this.ControlViewModel.Loaded += this.ControlViewModelLoaded;
this.ControlViewModel.Unloaded += (o, args) => this.Cleanup();
}
/// <summary>
/// Gets the control view model.
/// </summary>
public IControlViewModel ControlViewModel { get; private set; }
/// <summary>
/// The control view model_ loaded.
/// </summary>
/// <param name="sender">
/// The sender.
/// </param>
/// <param name="e">
/// The e.
/// </param>
private void ControlViewModelLoaded(object sender, EventArgs e)
{
//TODO : 加載數據
}
}
注: 此處是第一篇關於MVVM模式的文章,有關MVVM的基礎知識,可以通過百度後者GOOGLE可以查閱,本文不做詳解。
本文是基於MVVMLight框架設計的,對於如何使用MVVMLight框架的,本文不做詳解,如有感興趣的,可參考:點擊打開鏈接。
本人QQ:351157970.歡迎討論!
注1:該類在MVVMLight中,使用的MVVM模式是基於MVVMLight的