Abstract:
通过一个简单的 web application, 学习以下内容:
(1) ListView control
(2) User control
(3) Handle ViewState in User control
(4) FindControl() usage, especially when there is a Master page.
本文主要讲述第一部分,即如何使用ListView控件。
虽然GridView功能非常强大,但是有时候用GridView却不是非常方便。比如说要实现下面这个页面,
数据结构是分层次,第一层次是student的基本信息,第二层是该student的每门课的分数。对于这种分层次的数据结构,如果用GridView来做数据绑定控件,是很不直观的。因为GridView非常适合扁平的数据结构,如果用GridView来显示的话,需要把已有的数据结构做“扁平化”处理。而用ListView会很直观,不需要做这些处理。
简单起见,数据源采用ObjectDataSource,首先定义下相关的Model和Controller,代码如下:
StudentModel
1: public class StudentModel
2: {
3: public int ID { get; set; }
4:
5: public string Name { get; set; }
6:
7: public string PassRate
8: {
9: get
10: {
11:
12: if (CourseScoreList != null)
13: {
14: float aCoursePassed = 0;
15:
16: foreach (CourseScoreModel aCourse in this.CourseScoreList)
17: {
18: if (aCourse.CourseScore >= 60)
19: {
20: aCoursePassed++;
21: }
22: }
23:
24: return string.Format("{0:P}", aCoursePassed / this.CourseScoreList.Count);
25:
26: }
27:
28: return "100%";
29: }
30: }
31:
32:
33: public IList<CourseScoreModel> CourseScoreList
34: {
35: get;
36: set;
37: }
38:
39: }
40:
41: public class CourseScoreModel
42: {
43: public string CourseName { get; set; }
44:
45: public double CourseScore { get; set; }
46:
47: }
StudentController
1: public class StudentController
2: {
3:
4: private IList<StudentModel> GetStudentsNoSort()
5: {
6: List<StudentModel> aStudentList = new List<StudentModel>();
7:
8: StudentModel aStudentModel = new StudentModel
9: {
10: ID = 101,
11: Name = "Frank",
12: };
13:
14: List<CourseScoreModel> aCourseList = new List<CourseScoreModel>();
15:
16: CourseScoreModel aCourseScoreModel = new CourseScoreModel
17: {
18: CourseName = "Math",
19: CourseScore = 67
20: };
21: aCourseList.Add(aCourseScoreModel);
22:
23: aCourseScoreModel = new CourseScoreModel
24: {
25: CourseName = "English",
26: CourseScore = 45
27: };
28: aCourseList.Add(aCourseScoreModel);
29:
30: aStudentModel.CourseScoreList = new List<CourseScoreModel>(aCourseList);
31: aStudentList.Add(aStudentModel);
32:
33: aStudentModel = new StudentModel
34: {
35: ID = 102,
36: Name = "Dan",
37: CourseScoreList = new List<CourseScoreModel>(aCourseList),
38: };
39:
40: aStudentList.Add(aStudentModel);
41:
42: return aStudentList;
43: }
44:
45:
46: public IList<StudentModel> GetStudents(String SortExpression)
47: {
48:
49: IList<StudentModel> aStudentList = GetStudentsNoSort();
50:
51: if (string.IsNullOrEmpty(SortExpression))
52: {
53: return aStudentList;
54: }
55:
56: String[] aSortExpressionArray = SortExpression.Split(' ');
57:
58: PropertyInfo aPI = typeof(StudentModel).GetProperty(aSortExpressionArray[0]);
59:
60: if (aSortExpressionArray.Length == 1)
61: {
62: // Asscending Sort
63: (aStudentList as List<StudentModel>).Sort
64: (
65: (sm1, sm2) => string.Compare(aPI.GetValue(sm1, null).ToString(),
66: aPI.GetValue(sm2, null).ToString())
67: );
68: }
69: else
70: {
71: // Descending Sort(aStudentList as List<StudentModel>).Sort
72: (aStudentList as List<StudentModel>).Sort
73: (
74: (sm1, sm2) => string.Compare(aPI.GetValue(sm2, null).ToString(),
75: aPI.GetValue(sm1, null).ToString())
76: );
77: }
78:
79: return aStudentList;
80: }
81: }
数据结构定义好之后,就可以进行页面的编码了。 因为数据结构是两个层次,因此需要用到两层ListView,分别对应Student信息和相应的课程分数信息。
用ListView需要首先定义下它的LayoutTemplate,
1: <LayoutTemplate>
2: <table id="StudentListView" class="ListView" rules="all" cellspacing="0" border="1" style=" 100%; border-collapse: collapse;">
3: <tr class="ListHeader">
4: <td>ID</td>
5: <td><asp:LinkButton ID="SortByNameLinkButton" runat="server" CommandName="Sort" CommandArgument="Name">Name</asp:LinkButton></td>
6: <td>Pass Rate</td>
7: <td>Course Name</td>
8: <td>Course Score</td>
9: </tr>
10: <tr id="itemPlaceHolder" runat="server"></tr>
11: </table>
12: </LayoutTemplate>
不想GridView,我们需要自己来定义整个Table结构,因为对每一行来说都是每个Student信息,因此把每一行单独放到到一个placeholder 里面,注意这一句
<tr id="itemPlaceHolder" runat="server"></tr> runat="server" 是必须的, 而且id为itemPlaceHolder
接下来定义这个PlaceHolder的内容,
1: <ItemTemplate>
2: <tr>
3: <td><%1: # Eval("ID")%></td>
4: <td><%1: # Eval("Name")%></td>
5: <td><%1: # Eval("PassRate")%></td>
6: <td> </td>
7: <td> </td>
8: </tr>
9:
10: <asp:ListView ID="CourseListView" DataSource='<%# Eval("CourseScoreList") %>' runat="server">
11: <LayoutTemplate>
12: <tr id="itemPlaceHolder" runat="server" />
13: </LayoutTemplate>
14: <ItemTemplate>
15: <tr>
16: <td> </td>
17: <td> </td>
18: <td> </td>
19: <td><%1: # Eval("CourseName")%></td>
20: <td><%1: # Eval("CourseScore")%></td>
21: </tr>
22: </ItemTemplate>
23: </asp:ListView>
24:
25: </ItemTemplate>
还需要定义一个ObjectDataSource指向之前定义的数据对象,
1: <asp:ObjectDataSource ID="StudentObjectDataSource" runat="server"
2: onobjectcreating="StudentObjectDataSource_ObjectCreating"
3: SortParameterName="SortExpression"
4: SelectMethod="GetStudents" TypeName="Fangwen.Yu.ListViewDemo.StudentController">
5: <SelectParameters>
6: <asp:Parameter Name="SortExpression" Type="String" />
7: </SelectParameters>
8: </asp:ObjectDataSource>
最后要注意一下,这里面关于对列Name排序的处理。
因为ListView不像GridView自动支持排序功能,当用鼠标点击表头的响应列,这列的数据会自动进行排序。想让ListView也有这种效果,需要自己编程来实现。
(1) 首先在Table中把列Name的表头控件设置成LinkButton,如下
<td><asp:LinkButton ID="SortByNameLinkButton" runat="server" CommandName="Sort" CommandArgument="Name">
Name
</asp:LinkButton>
</td>
特别注意,这里面两个参数CommandName和CommandArgument的设置,CommandName必须设置成“Sort”,CommandArgument设置成该列对应数据源的字段名,此例中为”Name”.
(2) 在ObjectDataSource中设置属性SortParameterName,该属性的值与SelectMethod对应的方法的参数名一致,此例为"SortExpression”。
(3) 在SelectMethod中进行处理,如下所示:
if (string.IsNullOrEmpty(SortExpression)) { return aStudentList; } String[] aSortExpressionArray = SortExpression.Split(' '); PropertyInfo aPI = typeof(StudentModel).GetProperty(aSortExpressionArray[0]); if (aSortExpressionArray.Length == 1) { // Asscending Sort (aStudentList as List<StudentModel>).Sort ( (sm1, sm2) => string.Compare(aPI.GetValue(sm1, null).ToString(), aPI.GetValue(sm2, null).ToString()) ); } else { // Descending Sort
(aStudentList as List<StudentModel>).Sort ( (sm1, sm2) => string.Compare(aPI.GetValue(sm2, null).ToString(), aPI.GetValue(sm1, null).ToString()) ); }
当页面第一次Load的时候,参数SortExpression为空字符串,因此需要首先判断一下参数是否为Empty,如果是则直接返回,不作排序处理。SortExpression的值包含两部分,第一部分是需要排序的字段,第二部分是排序方向 (特别注意,如果是升序排序,则这部分为NULL, 否则为字符串”DESC”. 因此需要对这个参数进行相应处理。
总结:
(1) ListView的优势--层次数据结构
(2) 自定义排序需要注意的地方
-- To Be Continued--