[VS2010 Online]初窺ASP.NET MVC(4) - GridView控制項的使用
在 [初窺ASP.NET MVC (3) - 控制項的使用] 我們談了蠻多的控制項,但是眼尖的你有沒有發現到,
過去我們在 ASP.NET 常用來顯示多筆資料的 GridView 老兄怎麼沒有登場呢?
筆者接下來就來介紹如何使用GridView:
1.
首先,建立一個全新的 ASP.NET MVC Web Apllication專案。
2.
在專案中新增一個 LINQ to SQL 的物件,這邊我們把它命名為Northwind.dbml。
3.
這次拿北風的 Customer 來作為範例:
4.
接下來,來處理分頁的部份,在Controller加入一個PagedList.cs檔案,這邊會透過PagedList<T>類別來處理:
這裡定義了 PageIndex、PageSize、TotalItemCount、TotalPageCount、SortExpression
以及 IdentityColumnName 屬性。分別用來處理當前頁面、每頁數量、資料列總數、頁面總數、
排序以及資料的 PK。
5.
然後針對LINQ的查詢以及回傳的List型別,我們建立一個PageLinqExtensions的類別,其中包含了三個擴充方法
(extension method),這三個擴充方法分別是3~12行的,提供 pageIndex、pageSize輸入;14~23行,提供
pageIndex、pageSize 以及 identityColumnName 輸入;25~41行,其中包含 pageIndex、pageSize、
identityColumnName以及排序所需的字串:
1: public static class PageLinqExtensions
2: {
3: public static PagedList<T> ToPagedList<T>
4: (
5: this IQueryable<T> allItems,
6: int? pageIndex,
7: int pageSize
8: )
9: {
10: return ToPagedList<T>(allItems, pageIndex, pageSize,null, String.Empty);
11:
12: }
13:
14: public static PagedList<T> ToPagedList<T>
15: (
16: this IQueryable<T> allItems,
17: int? pageIndex,
18: int pageSize,
19: string identityColumnName
20: )
21: {
22: return ToPagedList<T>(allItems, pageIndex, pageSize, identityColumnName, String.Empty);
23: }
24:
25: public static PagedList<T> ToPagedList<T>
26: (
27: this IQueryable<T> allItems,
28: int? pageIndex,
29: int pageSize,
30: string identityColumnName,
31: string sort
32: )
33: {
34: var truePageIndex = pageIndex ?? 0;
35: var itemIndex = truePageIndex * pageSize;
36: var pageOfItems = allItems.Skip(itemIndex).Take(pageSize);
37: var totalItemCount = allItems.Count();
38:
39: return new PagedList<T>(pageOfItems, truePageIndex, pageSize, totalItemCount,identityColumnName, sort);
40:
41: }
42:
43: }
6.
接下來,處理GridView的功能設定,我們建立一個 GridViewOption.cs 檔案,然後在類別中定義顯示編輯、刪除
功能的相關屬性,像是按鈕的內容、是否顯示以及對應的Action:
1: public class GridViewOption
2: {
3: private bool showEditButton = true;
4: private bool showDeleteButton = true;
5:
6: private string editButtonText = "Edit";
7: private string deleteButtonText = "Delete";
8:
9: private string editAction = "Edit";
10: private string deleteAction = "Delete";
11:
12: private string[] columns;
13:
14: public string[] Columns
15: {
16: get { return columns ; }
17: set { columns= value; }
18: }
19:
20:
21: public bool ShowEditButton
22: {
23: get { return showEditButton; }
24: set { showEditButton = value; }
25: }
26:
27: public bool ShowDeleteButton
28: {
29: get { return showDeleteButton; }
30: set { showDeleteButton = value; }
31: }
32:
33:
34: public string EditButtonText
35: {
36: get { return editButtonText; }
37: set { editButtonText = value; }
38: }
39:
40: public string DeleteButtonText
41: {
42: get { return deleteButtonText; }
43: set { deleteButtonText = value; }
44: }
45:
46:
47: public string EditAction
48: {
49: get { return editAction; }
50: set { editAction = value; }
51: }
52:
53: public string DeleteAction
54: {
55: get { return deleteAction; }
56: set { deleteAction = value; }
57: }
58: }
7.
接下來,我們來定義 GridView 的顯示內容,先新增一個 GridViewHelper 類別,然後在裡面定義三個擴充方法,
這三個方法會去處理Model、要顯示的內容以及編輯、刪除按鈕。程式碼可以參考如下:
1: public static class GridViewHelper
2: {
3: public static string GridView<T>(this HtmlHelper helper)
4: {
5: return GridView<T>(helper, null, null,new GridViewOption());
6: }
7:
8: public static string GridView<T>(this HtmlHelper helper, object data)
9: {
10: return GridView<T>(helper, data, null,new GridViewOption());
11: }
12:
13: public static string GridView<T>(this HtmlHelper helper, object data, string[] columns, GridViewOption options)
14: {
15:
16: // Get items
17: var items = (IEnumerable<T>)data;
18: if (items == null)
19: items = (IEnumerable<T>)helper.ViewData.Model;
20:
21: // Get column names
22: if (columns == null)
23: columns = typeof(T).GetProperties().Select(p => p.Name).ToArray();
24:
25: // Create HtmlTextWriter
26: var writer = new HtmlTextWriter(new StringWriter());
27:
28: // Open table tag
29: writer.RenderBeginTag(HtmlTextWriterTag.Table);
30:
31: // Render table header
32: writer.RenderBeginTag(HtmlTextWriterTag.Thead);
33: RenderHeader(helper, writer, columns, options);
34: writer.RenderEndTag();
35:
36: string identityColumnName= ((PagedList<T>)items).IdentityColumnName ;
37:
38: // Render table body
39: writer.RenderBeginTag(HtmlTextWriterTag.Tbody);
40: foreach (var item in items)
41: RenderRow<T>(helper, writer, columns, item, identityColumnName, options);
42: writer.RenderEndTag();
43:
44:
45: RenderPagerRow<T>(helper, writer, (PagedList<T>)items, columns.Count());
46:
47: // Close table tag
48: writer.RenderEndTag();
49:
50: // Return the string
51: return writer.InnerWriter.ToString();
52: }
53:
54:
55: private static void RenderHeader(HtmlHelper helper, HtmlTextWriter writer, string[] columns, GridViewOption options)
56: {
57: writer.RenderBeginTag(HtmlTextWriterTag.Tr);
58: int i = 0;
59:
60: foreach (var columnName in columns)
61: {
62: writer.RenderBeginTag(HtmlTextWriterTag.Th);
63: var currentAction = (string)helper.ViewContext.RouteData.Values["action"];
64:
65: string link=null;
66: if (options.Columns == null)
67:
68: link = helper.ActionLink(columnName, currentAction, new { sort = columnName }).ToHtmlString();
69:
70: else
71: {
72:
73: link = helper.ActionLink(options.Columns[i], currentAction, new { sort = columnName }).ToHtmlString();
74: i++;
75: }
76: writer.Write(link);
77: writer.RenderEndTag();
78:
79:
80:
81: }
82: // Show edit column?
83: bool showEditColumn = options.ShowEditButton || options.ShowDeleteButton;
84:
85: if (showEditColumn)
86: {
87: writer.RenderBeginTag(HtmlTextWriterTag.Th);
88: writer.Write(helper.Encode(""));
89: writer.RenderEndTag();
90: }
91: writer.RenderEndTag();
92: }
93:
94: private static void RenderRow<T>(HtmlHelper helper, HtmlTextWriter writer, string[] columns, T item ,string identityColumnName, GridViewOption options)
95: {
96: writer.RenderBeginTag(HtmlTextWriterTag.Tr);
97: foreach (var columnName in columns)
98: {
99: writer.RenderBeginTag(HtmlTextWriterTag.Td);
100: var value = typeof(T).GetProperty(columnName).GetValue(item, null) ?? String.Empty;
101: writer.Write(helper.Encode(value.ToString()));
102: writer.RenderEndTag();
103: }
104:
105: // Show edit column?
106: bool showEditColumn = options.ShowEditButton || options.ShowDeleteButton;
107:
108: if (showEditColumn)
109: {
110: var identityVaule = typeof(T).GetProperty(identityColumnName).GetValue(item, null);
111: writer.RenderBeginTag(HtmlTextWriterTag.Td);
112:
113: if ( options.ShowEditButton)
114: {
115: var link = helper.ActionLink(options.EditButtonText,options.EditAction , new { id =identityVaule });
116: writer.Write(link);
117: writer.Write(" ");
118: }
119:
120: if (options.ShowDeleteButton )
121: {
122: var link = helper.ActionLink(options.DeleteButtonText, options.DeleteAction , new { id = identityVaule });
123: writer.Write(link);
124: }
125:
126: writer.RenderEndTag();
127: }
128:
129: writer.RenderEndTag();
130: }
131:
132: private static void RenderPagerRow<T>(HtmlHelper helper, HtmlTextWriter writer, PagedList<T> items, int columnCount)
133: {
134: int nrOfPagesToDisplay = 10;
135:
136: // Don't show paging UI for only 1 page
137: if (items.TotalPageCount == 1)
138: return;
139:
140: // Render page numbers
141: writer.RenderBeginTag(HtmlTextWriterTag.Tr);
142: writer.AddAttribute(HtmlTextWriterAttribute.Colspan, columnCount.ToString());
143: writer.RenderBeginTag(HtmlTextWriterTag.Td);
144: var currentAction = (string)helper.ViewContext.RouteData.Values["action"];
145:
146: if (items.PageIndex >= 1)
147: {
148: var linkText = String.Format("{0}", "<<<");
149: var link = helper.ActionLink(linkText, currentAction, new { page = items.PageIndex, sort = items.SortExpression });
150: writer.Write(link + " ");
151: }
152:
153: int start = 0;
154: int end = items.TotalPageCount;
155:
156: if (items.TotalPageCount > nrOfPagesToDisplay)
157: {
158: int middle = (int)Math.Ceiling(nrOfPagesToDisplay / 2d) - 1;
159: int below = (items.PageIndex - middle);
160: int above = (items.PageIndex + middle);
161:
162: if (below < 4)
163: {
164: above = nrOfPagesToDisplay;
165: below = 0;
166: }
167: else if (above > (items.TotalPageCount - 4))
168: {
169: above = items.TotalPageCount;
170: below = (items.TotalPageCount - nrOfPagesToDisplay);
171: }
172:
173: start = below;
174: end = above;
175: }
176:
177: if (start > 3)
178: {
179: var linkText = String.Format("{0}", "1");
180: var link = helper.ActionLink(linkText, currentAction, new { page = 1, sort = items.SortExpression });
181: writer.Write(link + " ");
182:
183: linkText = String.Format("{0}", "2");
184: link = helper.ActionLink(linkText, currentAction, new { page = 2, sort = items.SortExpression });
185: writer.Write(link + " ");
186:
187: writer.Write(String.Format("{0}", "..."));
188: }
189:
190: for (var i = start; i < end; i++)
191: {
192:
193: if (i == items.PageIndex)
194: {
195: writer.Write(String.Format("<strong>{0}</strong> ", i + 1));
196: }
197: else
198: {
199: var linkText = String.Format("{0}", i + 1);
200: var link = helper.ActionLink(linkText, currentAction, new { page = i + 1, sort = items.SortExpression });
201: writer.Write(link + " ");
202: }
203:
204: }
205:
206: if (end < (items.TotalPageCount - 3))
207: {
208: writer.Write(String.Format("{0}", "..."));
209:
210: var linkText = String.Format("{0}", items.TotalPageCount - 1);
211: var link = helper.ActionLink(linkText, currentAction, new { page = items.TotalPageCount - 1, sort = items.SortExpression });
212: writer.Write(link + " ");
213:
214: linkText = String.Format("{0}", items.TotalPageCount);
215: link = helper.ActionLink(linkText, currentAction, new { page = items.TotalPageCount, sort = items.SortExpression });
216: writer.Write(link + " ");
217: }
218:
219:
220: if (items.PageIndex + 2 <= items.TotalPageCount)
221: {
222:
223: var linkText = String.Format("{0}", ">>>");
224: var link = helper.ActionLink(linkText, currentAction, new { page = items.PageIndex + 2, sort = items.SortExpression });
225: writer.Write(link + " ");
226: }
227:
228: writer.RenderEndTag();
229: writer.RenderEndTag();
230: }
231:
232: }
這段程式碼分成四個部份,3~52行處理Model、顯示內容以及編輯刪除的設定。55~92行處理GridView的header。
94~130行處理GridView的內容。第四部份則是處理頁數的顯示。
8.
HomeController如下設定:
1: public class HomeController : Controller
2: {
3: NorthwindDataContext db = new NorthwindDataContext();
4:
5: public ActionResult Index(string sort, int? page)
6: {
7: ViewData["Message"] = "GridView!!";
8:
9: page = page ?? 0;
10: if (page >= 1) page = page - 1;
11:
12: if (sort != null)
13: {
14: var model1 = (from c in db.Customers
15: select c)
16: .OrderBy(sort)
17: .ToPagedList(page, 5, "CustomerID", sort);
18: return View(model1);
19: }
20: else
21: {
22: var model2 = (from c in db.Customers
23: select c).ToPagedList(page, 5, "CustomerID");
24: return View(model2);
25:
26: }
27:
28: }
Index.aspx設定:
1: <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<PagedList<Customer>>" %>
2: <%@ Import Namespace ="MvcApplication3.Models" %>
3: <%@ Import Namespace ="Test" %>
4:
5: <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
6: Index
7: </asp:Content>
8:
9: <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
10:
11: <h2><%1: = Html.Encode(ViewData["Message"])%></h2>
12: <p>Show GridView</p>
13:
14: <%1: =Html.GridView<Customer>(Model, new string[] { "CustomerID", "CompanyName", "ContactName", "Address", "City" },2: new GridViewOption() )3:
4:
%>
15: </asp:Content>
顯示結果:
試煉大會,我們下次見。
如果您有微軟技術開發的問題,可以到MSDN Forum發問。
如果您有微軟IT管理的問題,可以到TechNet Forum發問喔。