概述
在Web Client Software Factory系列(3):View-Presenter模式中提到,表示器包含了響應使用者事件邏輯以及一些View的狀態等,在Web Client Software Factory中包含了一個名為ObjectContainerDataSource的資料來源控制項,它為View-Presenter模式和資料繫結之間提供了橋樑,ObjectContainerDataSource可以簡單的理解為用來包行對象的容器。它的處理過程如所示:
下面我們將通過一個完成的實力來示範如何使用View-Presenter模式和ObjectContainerDataSource控制項進行資料繫結。按照上一篇所講的,我們先在Product業務模組下添加一個NewProduct視圖。
在視圖中添加ObjectContainerDataSource控制項
之前請先在工具箱中添加ObjectContainerDataSource控制項,位於Microsoft.Practices.Web.UI.WebControls.dll下,拖拽ObjectContainerDataSource控制項到NewProduct.aspx頁面上。
接下來要做的就是配置ObjectContainerDataSource了,其實要配置也就是DataObjectTypeName屬性而已,即ObjectContainerDataSource控制項要包含的對象的類型。選擇之前我們編寫Product實體類,配置完成後ASPX中代碼如下:
<asp:Content ID="content1" ContentPlaceHolderID="DefaultContent" Runat="Server"><h1>NewProduct</h1><pp:ObjectContainerDataSource ID="ObjectContainerDataSource2" runat="server"DataObjectTypeName="WebClientDemo1.Products.ModuleEntities.Product" /></asp:Content>
這裡配置DataObjectTypeName屬性時有兩點需要注意:
1.如果實現Insert、Update、Delete操作,所配置的DataObjectTypeName參數所對應的類型要有一個無參的建構函式;
2.如果實現Update、Delete操作,所配置的DataObjectTypeName參數對應的類型要有一個屬效能夠唯一表示該類型的一個執行個體,其實就是對應資料庫中的主鍵,也支援聯合主鍵,這個不難理解,想想SQL語句就知道了。
添加DetailsView、GridView綁定到ObjectContainerDataSource
在NewProduct.aspx頁面上添加DetailsView、GridView控制項,分布指定它們的DataSourceID為ObjectContainerDataSource1,如所示:
設定完成後的代碼如下:
<asp:Content ID="content" ContentPlaceHolderID="DefaultContent" Runat="Server"><h1>NewProduct</h1><hr/><asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="Id" DataSourceID="ObjectContainerDataSource1" Width="400px"><Columns><asp:BoundField DataField="Name" HeaderText="Name" SortExpression="Name" /><asp:BoundField DataField="Brand" HeaderText="Brand" SortExpression="Brand" /><asp:CommandField ShowCancelButton="False" ShowDeleteButton="True" /></Columns></asp:GridView><hr/><asp:DetailsView ID="DetailsView1" runat="server" AutoGenerateRows="False" DataSourceID="ObjectContainerDataSource1"DefaultMode="Insert" Height="50px" Width="400px" DataKeyNames="Id"><Fields><asp:BoundField DataField="Name" HeaderText="Name" SortExpression="Name" /><asp:BoundField DataField="Brand" HeaderText="Brand" SortExpression="Brand" /><asp:CommandField ButtonType="Button" InsertText=" Add " ShowCancelButton="False"ShowInsertButton="True" /></Fields></asp:DetailsView><pp:ObjectContainerDataSource ID="ObjectContainerDataSource1" runat="server"DataObjectTypeName="WebClientDemo1.Products.ModuleEntities.Product" /></asp:Content>
實現資料的Insert、Update、Delete
為了實現的資料的增刪改,我們需要修改在Web Client Software Factory系列(2):Composite Web應用程式塊寫過的Service,這裡為了示範資料就不從資料庫中讀取了,而是儲存在Session中。
IProductDataService介面:
public interface IProductDataService{Product GetProductById(string id);List<Product> Products { get;set;}void InsertProduct(Product product);void UpdateProduct(Product product);void DeleteProduct(Product product);}
Service實現:
public class ProductDataService : IProductDataService{private List<Product> _products;public List<Product> Products{get{_products = HttpContext.Current.Session["products"] as List<Product>;if (_products == null){_products = new List<Product>();}return _products;}set{HttpContext.Current.Session["products"] = value;}}public void InsertProduct(Product product){product.Id = Guid.NewGuid().ToString();_products = HttpContext.Current.Session["products"] as List<Product>;if (_products == null){_products = new List<Product>();}_products.Add(product);HttpContext.Current.Session["products"] = _products;}public void UpdateProduct(Product product){Product result = FindProduct(Products, product);if (result != null){result.Name = product.Name;result.Brand = product.Brand;}}public void DeleteProduct(Product product){Product result = FindProduct(Products, product);if (result != null){Products.Remove(result);}}private static Product FindProduct(List<Product> products, Product product){return products.Find(delegate(Product match){return product.Id == match.Id;});}}
開啟視圖INewProduct,編寫如下代碼
public interface INewProduct{List<Product> Products { set;}}
並在NewProduct.aspx.cs中實現View介面
public List<Product> Products{set{this.ObjectContainerDataSource1.DataSource = value;}}
接下來我們要做的就是實現Controller,在Web Client Software Factory系列(2):Composite Web應用程式塊中註冊和使用服務一節中已經講過了,直接給出代碼:
public class ProductsController{public ProductsController(){}private IProductDataService _productDataService;[ServiceDependency]public IProductDataService ProductDataService{set { _productDataService = value; }}public List<Product> Products{get{return _productDataService.Products;}set{_productDataService.Products = value;}}public void InsertProduct(Product product){_productDataService.InsertProduct(product);}public void UpdateProduct(Product product){_productDataService.UpdateProduct(product);}public void DeleteProduct(Product product){_productDataService.DeleteProduct(product);}}
實現我們的Presenter,具體的在Web Client Software Factory系列(3):視圖、表示器和控制器中已經講過
public class NewProductPresenter : Presenter<INewProduct>{private ProductsController _controller;public NewProductPresenter([CreateNew] ProductsController controller){_controller = controller;}public override void OnViewLoaded(){View.Products = _controller.Products;}public override void OnViewInitialized(){}public void OnProductInserted(Product product){_controller.InsertProduct(product);}public void OnProductUpdated(Product product){_controller.UpdateProduct(product);}public void OnProductDeleted(Product product){_controller.DeleteProduct(product);}}
最後為ObjectContainerDataSource控制項添加相關的事件,並具體的操作交給Presenter:
protected void ObjectContainerDataSource1_Inserted(object sender, ObjectContainerDataSourceStatusEventArgs e){_presenter.OnProductInserted((Product)e.Instance);}protected void ObjectContainerDataSource1_Updated(object sender, ObjectContainerDataSourceStatusEventArgs e){_presenter.OnProductUpdated((Product)e.Instance);}protected void ObjectContainerDataSource1_Deleted(object sender, ObjectContainerDataSourceStatusEventArgs e){_presenter.OnProductDeleted((Product)e.Instance);}
這裡需要說明的是ObjectContainerDataSourceStatusEventArgs有兩個特別重要的屬性是Instance和AffectedRows,ObjectContainerDataSource控制項通過反射建立它所包含對象的類型的實力Instance,AffectedRows是受影響的行數。
運行後如下:
分頁和排序
如果使用ObjectContainerDataSource預設的分頁和排序功能,需要設定如下兩個屬性:
UsingServerPaging="True"UsingServerSorting="True"
並編寫Selecting事件:
protected void CustomersDataSource_Selecting(object sender, ObjectContainerDataSourceSelectingEventArgs e){_presenter.OnSelecting(e.Arguments.StartRowIndex, e.Arguments.MaximumRows, e.Arguments.SortExpression);}
剩下的就到Presenter中處理分頁了:)
結束語
關於Web Client Software Factory中使用View-Presenter模式進行資料繫結和ObjectContainerDataSource控制項就到這裡了,希望對您有所協助。
範例程式碼下載:/Files/Terrylee/WebClientDemo2.rar