返回首頁
當前位置: 主頁 > 網絡編程 > .Net實例教程 >

在Silverlight中應用MVVM模式教程代碼

時間:2012-02-11 18:31來源:知行網www.wtckvq.live 編輯:麥田守望者

MVVM:即Model View ViewModel三層,

個人感覺歸根結底MVVM其實就是MVC的一個變種,ViewModel有一個很明顯的優點:可降低View->Control的偶合,像Flash/Silverlight這類RIA應用,在View層中會有不少實現動畫效果的代碼,而傳統的MVC結構,在實現數據更新時,不可避免地要在View中寫很多Control代碼,這樣的話容易造成結構混亂,

但MVVM基于事件綁定機制,在View層中只要完成綁定即可,View會自動更新Model,Model再通知Control,這樣就可大量減少View層中的Control代碼。

下面舉個例子說明:
 

在Silverlight中應用MVVM模式教程代碼
 

我們這里有一個可分組的DataGrid控件,現在的需求是: 當用戶單擊Complete時,實現一些控制操作,如更新某個圖表,或更新后臺數據庫等。

首先:我們需要創建一個Model,此Model繼承INotifyPropertyChanged接口,會強制實現PropertyChangedEventHandler事件即屬性更改事件,在Complete的值發生改變時(View->Model)冒出這個事件。

//Model public class Task :INotifyPropertyChanged { public string ProjectName { get; set; } public string TaskName { get; set; } public DateTime DueDate { get; set; } // Private task data. private bool m_Complete = false; public bool Complete { get { return this.m_Complete; } set { if (value != this.m_Complete) { this.m_Complete = value; NotifyPropertyChanged("Complete"); } } } public string Notes { get; set; } #region INotifyPropertyChanged 成員 public event PropertyChangedEventHandler PropertyChanged; private void NotifyPropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } #endregion } 然后: 我們需要在Control層中生成綁定數據源,并在數據源上偵聽這個屬性更改事件(Model->Control),由于多用到泛型集合,所以我們希望在對象被加入集合列表(List)時自動綁定這個事件,因此我們新建一個類以簡化這個操作,事實上ObservableCollection中已經包含了PropertyChangedEventHandler事件 ,可能是出于性能的考慮,將其設為了protected類型,并且沒有進行任何操作,因此我們需要新建一個子類來實現他: public class ViewModelCollection<T> : ObservableCollection<T> { public ViewModelCollection():base() { } public new void Add(T item) { //在添加時自動綁定 ((INotifyPropertyChanged)item).PropertyChanged += new PropertyChangedEventHandler(ViewModelCollection_PropertyChanged); base.Add(item); } #region INotifyPropertyChanged 成員 public new event PropertyChangedEventHandler PropertyChanged; void ViewModelCollection_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (PropertyChanged != null) { //繼續向上冒出事件,并傳遞發生改變的對象 PropertyChanged(sender, new PropertyChangedEventArgs(e.PropertyName)); } } #endregion } 接著: 我們就可以在ViewModel中使用這個泛型集合了,并添加對屬性更改事件的偵聽。 這里使用的PagedCollectionView對象僅僅是為DataGrid控件提供分組數據源,這也是一個相當強大的類,大家可以查閱相當文檔學習他的使用。 //ViewModel public class ViewModel { public PagedCollectionView TaskBinding() { // 生成泛型集合數據源。 ViewModelCollection<Task> taskList = new ViewModelCollection<Task>(); for (int i = 1; i <= 14; i++) { taskList.Add(new Task() { ProjectName = "Project " + ((i % 3) + 1).ToString(), TaskName = "Task " + i.ToString(), DueDate = DateTime.Now.AddDays(i), Complete = (i % 2 == 0), Notes = "Task " + i.ToString() + " is due on " + DateTime.Now.AddDays(i) + ". Lorum ipsum..." }); } taskList.PropertyChanged += new PropertyChangedEventHandler(taskList_PropertyChanged); PagedCollectionView taskListView = new PagedCollectionView(taskList); // 添加要進行分組的屬性 taskListView.GroupDescriptions.Add(new PropertyGroupDescription("ProjectName")); taskListView.GroupDescriptions.Add(new PropertyGroupDescription("Complete")); return taskListView; } void taskList_PropertyChanged(object sender, PropertyChangedEventArgs e) { Task task = (Task)sender; MessageBox.Show(string.Format("Model Changed: IsComplete={0} PropertyName={1}", task.Complete, e.PropertyName)); //其他一些操作,如更新數據庫,圖表等 } }
最后: 我們就可以在View層中進行數據綁定了
public partial class MainPage : UserControl
{
private ViewModel controller;

public MainPage()
{
InitializeComponent();

controller = new ViewModel();
dataGrid1.ItemsSource = controller.TaskBinding();
}
}

最后看一看效果:當用戶單擊Complete列的選擇框時就會觸發Control中的控制代碼,從而不需要在View中書寫額外的代碼

 


完整代碼:
xaml文件:
<UserControl x:Class="DataGridGrouping.MainPage"
xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="600" Height="500">
<Grid x:Name="LayoutRoot" Background="White" Margin="10">
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<data:DataGrid x:Name="dataGrid1">
<data:DataGrid.RowGroupHeaderStyles>
<!-- Style for groups at top level -->
<Style TargetType="data:DataGridRowGroupHeader">
<Setter Property="PropertyNameVisibility" Value="Collapsed" />
<Setter Property="Background" Value="#FF112255" />
<Setter Property="Foreground" Value="#FFEEEEEE" />
<Setter Property="SublevelIndent" Value="15" />
</Style>
<!-- Style for groups under the top level -->
<Style TargetType="data:DataGridRowGroupHeader">
<Setter Property="Background" Value="#44225566" />
</Style>
</data:DataGrid.RowGroupHeaderStyles>
</data:DataGrid>
</Grid>
</UserControl>


CS:文件:
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Collections.Specialized;
using System.Collections.Generic;

namespace DataGridGrouping
{
public partial class MainPage : UserControl
{
private ViewModel controller;

public MainPage()
{
InitializeComponent();

controller = new ViewModel();
dataGrid1.ItemsSource = controller.TaskBinding();
}
}

//ViewModel
public class ViewModel
{
public PagedCollectionView TaskBinding()
{
// 生成泛型集合數據源。
ViewModelCollection<Task> taskList = new ViewModelCollection<Task>();
for (int i = 1; i <= 14; i++)
{
taskList.Add(new Task()
{
ProjectName = "Project " + ((i % 3) + 1).ToString(),
TaskName = "Task " + i.ToString(),
DueDate = DateTime.Now.AddDays(i),
Complete = (i % 2 == 0),
Notes = "Task " + i.ToString() + " is due on "
+ DateTime.Now.AddDays(i) + ". Lorum ipsum..."
});
}
taskList.PropertyChanged += new PropertyChangedEventHandler(taskList_PropertyChanged);

PagedCollectionView taskListView = new PagedCollectionView(taskList);
// 添加要進行分組的屬性
taskListView.GroupDescriptions.Add(new PropertyGroupDescription("ProjectName"));
taskListView.GroupDescriptions.Add(new PropertyGroupDescription("Complete"));

return taskListView;
}

void taskList_PropertyChanged(object sender, PropertyChangedEventArgs e)

------分隔線----------------------------
標簽(Tag):C# C#實例教程 c#基礎教程 C#源代碼 c#技巧
------分隔線----------------------------
推薦內容
猜你感興趣
深蓝海域APP