Web窗体模型绑定第二部分:数据筛选(ASP.NET vNext系列)

[原文发表地址] Web Forms Model Binding Part 2: Filtering Data (ASP.NET vNext Series)
[原文发表时间] 2011-09-12 14:18

Web窗体模型绑定第二部分:数据筛选(ASP.NET vNext系列)

这是我对ASP.NET vNext做的系列博文的第四篇。

下一版的.NET和Visual Studio包括了许多很棒的新功能。有了ASP.NET vNext,你会看到许多Web窗体和MVC的改进——还有ASP.NET核心库的改进。

今天的这篇博文是讨论Web窗体的新模型绑定支持的三篇博文的第二篇。模型绑定是ASP.NET Web窗体现有数据绑定系统的扩展,提供了代码为主的数据访问范例。它利用了我们最早介绍的ASP.NET MVC的一堆模型绑定概念的优势,并通过Web窗体服务器控制模型很好地将它们融合了起来。

在我第一篇模型绑定博文中我讨论了关于数据选择的一些基本内容。在今天的博文中,我们要看看如何在用户输入的基础上筛选数据,而同时又保持代码为主的数据访问方式。我会用两种方法教你做这个筛选,一种是用询问字符串输入,另一种则是通过下拉列表服务器控件的值。

准备开始

我们从向页面添加<asp:GridView>控件开始,对它进行配置,使用模型绑定来显示Northwind Products表中的数据。我们下面的GridView中有一个SelectMethod属性,设置为了GetProducts()——会使其在代码隐藏文件中调用GetProducts()函数,它使用的是Entity Framework Code First简单地返回绑定的Products表。

 <asp:GridView ID="productsGrid" SelectMethod="GetProducts" DataKeyNames="ProductID"
AllowPaging="true" AllowSorting="true" AutoGenerateColumns="false" runat="server">
 <Columns>
 <asp:BoundField DataField="ProductID" HeaderText="ID" />
 <asp:BoundField DataField="ProductName" HeaderText="Name" SortExpression="ProductName" />
 <asp:BoundField DataField="UnitPrice" HeaderText="Unit Price" SortExpression="UnitPrice" />
 <asp:BoundField DataField="UnitsInStock" HeaderText="# in Stock" SortExpression="UnitsInStock" />
 </Columns>
</asp:GridView>

以下是代码隐藏文件(包含GetProducts()函数)的样子:

 
public partial class Products : Page
{
 Northwind db = new Northwind();
  
 public IQueryable<Product> GetProducts()
 {
 return db.Products;
 }
}

运行这个页面,得到预期的结果表包含产品数据:

image

因为我们从GetProducts()函数中返回IQueryable<Product>,所以排序和分页是自动实现的(在数据库中完成,所以十分高效,只有我们需要的10个结果回到中间层)。

使用询问字符串参数筛选

我们现在来为我们的应用添加一些基础筛选支持。特别的是,我们来让用户能够有选择地根据产品名是否包含关键词筛选产品结果。我们使用询问字符串参数来特定关键词。比如,下面我们假定只想显示产品名中含有“chef”这个单词的产品:

image

 

如果没有特定关键词,那我们就会像之前那样显示所有的产品。

更新GetProducts函数

要实现筛选,我们要更新GetProducts()函数,使它含有如下关键词参数:

 public IQueryable<Product> GetProducts([QueryString]string keyword)
{
 IQueryable<Product> query = db.Products;
 
 if (!String.IsNullOrWhiteSpace(keyword))
 {
 query = query.Where(p => p.ProductName.Contains(keyword));
 }
  
 return query;
}

如果关键词为空,那么函数就会返回数据库中所有的产品。如果关键词被特定,那么我们就会进一步筛选询问结果,只显示那些包含关键词的产品。

了解值供应

看了上面的代码,你可能会注意到[QueryString]属性,我们把它应用到了关键词函数自变量。它会指示模型绑定系统尝试在运行时将询问字符串中的值“绑定”到这个参数,包括做任何对话要求的。

这些用户值的源代码被称为“值供应”,参数属性用来指示模型绑定系统,那些值供应使用的就叫做“值供应属性”。下一版的Web窗体会为所有Web窗体中用户常用的源代码输入连接值供应和相应的属性,比如询问字符串,cookies,form值,控件,viewstate,组件和资料。你还可以编写自己的自定义值供应。你写的值供应可以被授权在Web窗体和MVC中工作。

默认地,参数名称会被用作是值供应集合的关键字,所以在这个案例中,询问字符串中值会和“关键词”一起被查找,比如~/Products.aspx?keyword=chef。这个很容易被向参数属性输入所需的自变量关键词所覆盖。在我们的例子中,我们希望用户能使用常见的“q”询问字符串关键词来特定关键词:

 public IQueryable<Product> GetProducts([QueryString("q")]string keyword)

    
现在我们可以通过询问字符串输入关键词来筛选结果:

image

如果你想一下你现在是如何用代码实现这个的,它会需要好多行,比如,读取值,检查是否为空,尝试将其转换成需要的类型,检查对话是否成功,然后最后在询问中使用值。融合分页和排序支持(除去编辑支持)会把这个变得更复杂。模型绑定系统旨在减少编写这类不必要的代码,当你不得不写这些的时候,还会让你用最简单的方式在应用中呈现。

使用控件进行筛选

现在我们改变一下我们的例子,这样用户就能通过下拉菜单来选择一个分类来筛选产品了。

image

要做这个,我们要向标记中添加一个下拉列表,并进行配置,在代码隐藏文件中获取GetCategories()函数数据,使用其中的SelectMethod属性:

 <asp:DropDownList ID="category" SelectMethod="GetCategories"
 AppendDataBoundItems="true" AutoPostBack="true"
 DataTextField="CategoryName" DataValueField="CategoryID"
 runat="server">
 <asp:ListItem Value="" Text="(All)" />
</asp:DropDownList> 
<asp:GridView ID="productsGrid" SelectMethod="GetProducts" DataKeyNames="ProductID"
 AllowPaging="true" AllowSorting="true" AutoGenerateColumns="false" runat="server">
 <Columns>
 <asp:BoundField DataField="ProductID" HeaderText="ID" />
 <asp:BoundField DataField="ProductName" HeaderText="Name" SortExpression="ProductName" />
 <asp:BoundField DataField="UnitPrice" HeaderText="Unit Price" SortExpression="UnitPrice" />
 <asp:BoundField DataField="UnitsInStock" HeaderText="# in Stock" SortExpression="UnitsInStock" />
 </Columns>
</asp:GridView>

然后我们更新代码隐藏文件,使其包含新的GetCategories()函数(添加下拉列表控件),更新根据下拉列表中的已选择分类进行筛选的GetProducts() 函数:

 public partial class Products : Page
{
 Northwind db = new Northwind();
 
 // 
 // Select method for DropDownList
 
 public IEnumerable<Category> GetCategories()
 {
 return db.Categories.ToList();
 }
 // 
 // Select method for GridView
 
 public IQueryable<Product> GetProducts([Control] int? category)
 {
 IQueryable<Product> query = db.Products;
 
 if (categoryId.HasValue)
 {
 query = query.Where(p => p.CategoryID == category);
 }
 
 return query;
 }
}

注意上面我们是如何改变GetProducts()函数,把可空分类作为参数。然后我使用分类参数上的[Control]属性将其与“category”下拉列表控件值绑定。在GetProducts()函数中,我会检查是否默认(所有)值被选中——只筛选至特定分类如果下拉列表中选择的是非所有项目。

模型绑定系统会追踪参数值以选择函数来检测它们是否通过回发改变了。如果改变了,那就自动唤起相关数据控制,以自动重新绑定。这让页面创建更简单了,在需要的时候绑定,无需编写很多代码或者时刻注意Web窗体页面的周期。

现在当我们再次运行页面,我们可以选择下拉列表中的默认(所有)选项来显示所有产品,或者用选择分类来筛选产品。

image

  

分类和分页再一次自动实现(在数据库中完成所以很高效)无论我们是否筛选。

模型绑定和筛选的短视频

Damiana Edwards做了一个很棒的90秒视频,展示了使用模型绑定实行GridView场景和筛选。你可以点击这里观看90秒视频。

总结

ASP.NET vNext中最新的模型绑定支持是现有Web窗体数据绑定系统的完美进化。它让基于使用代码为主数据访问范例的用户输入进行数据筛选变得简单。你可以使用值供应属性来指示模型绑定,获取筛选值,你还可以为更复杂的场景编写自己的值供应。

在下一篇博文中,我们会看看如何使用模型绑定来编辑场景。

希望对你们有用。

Scott