Web Client Software Factory系列(4):数据绑定和ObjectContainerDataSource控件

概述

Web Client Software Factory系列(3):View-Presenter模式中提到,表示器包含了响应用户事件逻辑以及一些View的状态等,在Web Client Software Factory中包含了一个名为ObjectContainerDataSource的数据源控件,它为View-Presenter模式和数据绑定之间提供了桥梁,ObjectContainerDataSource可以简单的理解为用来包行对象的容器。它的处理过程如下图所示:

TerryLee_WCSF16

下面我们将通过一个完成的实力来演示如何使用View-Presenter模式和ObjectContainerDataSource控件进行数据绑定。按照上一篇所讲的,我们先在Product业务模块下添加一个NewProduct视图。

在视图中添加ObjectContainerDataSource控件

之前请先在工具箱中添加ObjectContainerDataSource控件,位于Microsoft.Practices.Web.UI.WebControls.dll下,拖拽ObjectContainerDataSource控件到NewProduct.aspx页面上。

TerryLee_WCSF17

接下来要做的就是配置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,如下图所示:

TerryLee_WCSF18

设置完成后的代码如下:

<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是受影响的行数。

运行后如下:

TerryLee_WCSF19

分页和排序

如果使用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

posted @ 2007-11-28 20:45  TerryLee  阅读(6704)  评论(24编辑  收藏  举报