ASP.NET MVC Tip #8 – Tạo ASP.NET MVC GridView Helper Method
Trong thủ thuật này, bạn sẽ tìm hiểu làm thế nào để mở rộng ASP.NET MVC framework với một phương pháp helper mới sẽ hiển thị một bảng HTML của dữ liệu trong cơ sở dữ liệu. Hiện nay, framework ASP.NET MVC không bao gồm bất cứ điều gì đó là tương đương trực tiếp đến ASP.NET Web Forms GridView ...
Trong thủ thuật này, bạn sẽ tìm hiểu làm thế nào để mở rộng ASP.NET MVC framework với một phương pháp helper mới sẽ hiển thị một bảng HTML của dữ liệu trong cơ sở dữ liệu.
Hiện nay, framework ASP.NET MVC không bao gồm bất cứ điều gì đó là tương đương trực tiếp đến ASP.NET Web Forms GridView control. Nếu bạn muốn hiển thị một bảng dữ liệu cơ sở dữ liệu thì bạn phải viết ra tất cả các HTML và script inline mỗi lần mà bạn muốn hiển thị dữ liệu. Trong thủ thuật này, tôi chỉ cho bạn làm thế nào để thêm một extension method GridView() vào lớp HtmlHelper.
Một phương pháp mở rộng là một phương pháp bổ sung vào một lớp bằng lớp khác. Bạn có thể sử dụng phương pháp mở rộng để cung cấp cho các lớp hiện có sức mạnh bổ sung. Trong trường hợp của chúng tôi, chúng tôi muốn cung cấp cho các lớp HtmlHelper, lớp mà bạn sử dụng trong một MVC View Page, một GridView() method mới mà sinh ra một bảng HTML của dữ liệu cơ sở dữ liệu.
Bạn tạo ra một extension method theo những cách khác nhau khi làm việc với Visual Basic .NET và khi làm việc với C #. Bạn tạo ra một phương pháp khuyến nông với Visual Basic.NET bằng cách tạo ra một chức năng mô-đun và trang trí trong các mô-đun với <mở rộng> thuộc tính. Bạn tạo ra một extension method với C # bằng cách tạo ra một lớp tĩnh và sử dụng các từ khóa này với tham số đầu tiên của mỗi phương pháp mở rộng hiển thị bởi lớp tĩnh.
Mã cho extension method GridView() được chứa trong Liệt kê 1.
Liệt kê 1 - GridExtensions.vb (VB)
1: Imports System 2: Imports System.Text 3: Imports System.Collections.Generic 4: Imports System.Linq 5: Imports System.Data.Linq.Mapping 6: Imports System.Data.Linq 7: Imports System.Web.UI 8: Imports System.Web.Mvc 9: Imports System.Web 10: Imports System.Runtime.CompilerServices 11: 12: 13: Namespace Helpers 14: 15: Public Module GridExtensions 16: 17: <Extension()> _ 18: Public Function GridView(ByVal htmlHelper As HtmlHelper, ByVal table As ITable) As String 19: Return GridView(htmlHelper, table, Nothing, New GridViewOptions()) 20: End Function 21: 22: <Extension()> _ 23: Public Function GridView(ByVal htmlHelper As HtmlHelper, ByVal table As ITable, ByVal headers As String()) As String 24: Return GridView(htmlHelper, table, headers, New GridViewOptions()) 25: End Function 26: 27: <Extension()> _ 28: Public Function GridView(ByVal htmlHelper As HtmlHelper, ByVal table As ITable, ByVal includeLinks As Boolean) As String 29: Return GridView(htmlHelper, table, Nothing, includeLinks) 30: End Function 31: 32: <Extension()> _ 33: Public Function GridView(ByVal htmlHelper As HtmlHelper, ByVal table As ITable, ByVal headers As String(), ByVal includeLinks As Boolean) As String 34: Dim options As New GridViewOptions() 35: If Not includeLinks Then 36: options.ShowViewButton = False 37: options.ShowEditButton = False 38: options.ShowDeleteButton = False 39: End If 40: Return GridView(htmlHelper, table, Nothing, options) 41: End Function 42: 43: <Extension()> _ 44: Public Function GridView(ByVal htmlHelper As HtmlHelper, ByVal table As ITable, ByVal headers As String(), ByVal options As GridViewOptions) As String 45: ' Show edit column? 46: Dim showEditColumn As Boolean = options.ShowViewButton Or options.ShowEditButton Or options.ShowDeleteButton 47: 48: ' Get identity column name 49: Dim identityColumnName As String = GridExtensions.GetIdentityColumnName(table) 50: 51: ' Get column names and headers 52: Dim columnNames = GridExtensions.GetColumnNames(table) 53: If IsNothing(headers) Then 54: headers = columnNames 55: End If 56: 57: ' Open table 58: Dim sb As New StringBuilder() 59: sb.AppendLine("<table>") 60: 61: ' Create Header Row 62: sb.AppendLine("<thead>") 63: sb.AppendLine("<tr>") 64: If showEditColumn Then 65: sb.Append("<th></th>") 66: End If 67: For Each header As String In headers 68: sb.AppendFormat("<th>{0}</th>", header) 69: Next 70: sb.AppendLine("</tr>") 71: sb.AppendLine("</thead>") 72: 73: ' Create Data Rows 74: sb.AppendLine("<tbody>") 75: sb.AppendLine("<tr>") 76: Dim row As Object 77: For Each row In table 78: If showEditColumn Then 79: Dim identityValue As Integer = CType(DataBinder.GetPropertyValue(row, identityColumnName), Integer) 80: sb.Append("<td><small>") 81: If (options.ShowViewButton) Then 82: sb.Append(htmlHelper.ActionLink(options.ViewButtonText, options.ViewAction, New With {.Id = identityValue})) 83: End If 84: sb.Append(" ") 85: If options.ShowEditButton Then 86: sb.Append(htmlHelper.ActionLink(options.EditButtonText, options.EditAction, New With {.Id = identityValue})) 87: sb.Append(" ") 88: End If 89: If options.ShowDeleteButton Then 90: sb.Append(htmlHelper.ActionLink(options.DeleteButtonText, options.DeleteAction, New With {.Id = identityValue})) 91: sb.Append("</small></td>") 92: End If 93: End If 94: For Each columnName As String In columnNames 95: Dim value As String = DataBinder.GetPropertyValue(row, columnName).ToString() 96: sb.AppendFormat("<td>{0}</td>", HttpUtility.HtmlEncode(value)) 97: Next 98: sb.AppendLine("</tr>") 99: Next 100: sb.AppendLine("</tbody>") 101: 102: sb.AppendLine("</table>") 103: Return sb.ToString() 104: End Function 105: 106: Public Function GetColumnNames(ByVal table As ITable) As String() 107: Return table.Context.Mapping.GetMetaType(table.ElementType).PersistentDataMembers.Select(Function(m) m.Name).ToArray() 108: End Function 109: 110: Public Function GetIdentityColumnName(ByVal table As ITable) As String 111: Return table.Context().Mapping().GetMetaType(table.ElementType).DBGeneratedIdentityMember().Name 112: End Function 113: End Module 114: 115: End Namespace
Listing 1 – GridExtensions.cs (C#)
1: using System; 2: using System.Text; 3: using System.Collections.Generic; 4: using System.Linq; 5: using System.Data.Linq.Mapping; 6: using System.Data.Linq; 7: using System.Web.UI; 8: using System.Web.Mvc; 9: using System.Web; 10: 11: namespace Tip8.Helpers 12: { 13: public static class GridExtensions 14: { 15: 16: public static string GridView(this HtmlHelper htmlHelper, ITable table) 17: { 18: return GridView(htmlHelper, table, null, new GridViewOptions()); 19: } 20: 21: public static string GridView(this HtmlHelper htmlHelper, ITable table, string[] headers) 22: { 23: return GridView(htmlHelper, table, headers, new GridViewOptions()); 24: } 25: 26: public static string GridView(this HtmlHelper htmlHelper, ITable table, bool includeLinks) 27: { 28: return GridView(htmlHelper, table, null, includeLinks); 29: } 30: 31: public static string GridView(this HtmlHelper htmlHelper, ITable table, string[] headers, bool includeLinks) 32: { 33: var options = new GridViewOptions(); 34: if (!includeLinks) 35: { 36: options.ShowViewButton = false; 37: options.ShowEditButton = false; 38: options.ShowDeleteButton = false; 39: } 40: return GridView(htmlHelper, table, null, options); 41: } 42: 43: public static string GridView(this HtmlHelper htmlHelper, ITable table, string[] headers, GridViewOptions options) 44: { 45: // Show edit column? 46: bool showEditColumn = options.ShowViewButton || options.ShowEditButton || options.ShowDeleteButton; 47: 48: // Get identity column name 49: string identityColumnName = GridExtensions.GetIdentityColumnName(table); 50: 51: // Get column names and headers 52: var columnNames = GridExtensions.GetColumnNames(table); 53: if (headers == null) 54: headers = columnNames; 55: 56: // Open table 57: var sb = new StringBuilder(); 58: sb.AppendLine("<table>"); 59: 60: // Create Header Row 61: sb.AppendLine("<thead>"); 62: sb.AppendLine("<tr>"); 63: if (showEditColumn) 64: sb.Append("<th></th>"); 65: foreach (String header in headers) 66: sb.AppendFormat("<th>{0}</th>", header); 67: sb.AppendLine("</tr>"); 68: sb.AppendLine("</thead>"); 69: 70: // Create Data Rows 71: sb.AppendLine("<tbody>"); 72: sb.AppendLine("<tr>"); 73: foreach (Object row in table) 74: { 75: if (showEditColumn) 76: { 77: int identityValue = (int)DataBinder.GetPropertyValue(row, identityColumnName); 78: sb.Append("<td><small>"); 79: if (options.ShowViewButton) 80: { 81: sb.Append(htmlHelper.ActionLink(options.ViewButtonText, options.ViewAction, new { Id = identityValue })); 82: sb.Append(" "); 83: } 84: if (options.ShowEditButton) 85: { 86: sb.Append(htmlHelper.ActionLink(options.EditButtonText, options.EditAction, new { Id = identityValue })); 87: sb.Append(" "); 88: } 89: if (options.ShowDeleteButton) 90: { 91: sb.Append(htmlHelper.ActionLink(options.DeleteButtonText, options.DeleteAction, new { Id = identityValue })); 92: } 93: sb.Append("</small></td>"); 94: } 95: foreach (string columnName in columnNames) 96: { 97: string value = DataBinder.GetPropertyValue(row, columnName).ToString(); 98: sb.AppendFormat("<td>{0}</td>", HttpUtility.HtmlEncode(value)); 99: } 100: sb.AppendLine("</tr>"); 101: } 102: sb.AppendLine("</tbody>"); 103: 104: sb.AppendLine("</table>"); 105: return sb.ToString(); 106: } 107: 108: public static string[] GetColumnNames(ITable table) 109: { 110: return table 111: .Context 112: .Mapping 113: .GetMetaType(table.ElementType) 114: .PersistentDataMembers.Select(m => m.Name) 115: .ToArray(); 116: } 117: 118: public static string GetIdentityColumnName(ITable table) 119: { 120: return table 121: .Context 122: .Mapping 123: .GetMetaType(table.ElementType) 124: .DBGeneratedIdentityMember 125: .Name; 126: } 127: } 128: 129: }
Liệt kê 1 chứa nhiều phiên bản của method GridView(). Mỗi phiên bản của method GridView() chấp nhận một bộ khác nhau của tham số. Ví dụ, phiên bản đầu tiên của method GridView() chấp nhận một LINQ to SQL bảng và sinh ra tất cả các cột và các hàng từ bảng. Các phiên bản khác của method GridView() cho phép bạn tùy chỉnh các tiêu đề GridView và chỉnh sửa liên kết.
MVC view trong Liệt kê 2 cho thấy nhiều cách gọi phương thức GridView() để hiển thị nội dung của một bảng cơ sở dữ liệu.
Liệt kê 2 - index.aspx (VB)
1: <%@ Page Language="VB" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="false" CodeBehind="Index.aspx.vb" Inherits="Tip8.Index" %> 2: <%@ Import Namespace="Tip8.Helpers" %> 3: 4: <asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server"> 5: 6: <h1>Simple Grid</h1> 7: 8: <%= Html.GridView(ViewData.Model) %> 9: 10: <h1>Simple Grid without Links</h1> 11: 12: <%= Html.GridView(ViewData.Model, false) %> 13: 14: <h1>Simple Grid with Custom Headers</h1> 15: 16: <%=Html.GridView(ViewData.Model, New String() {"AA", "BB", "CC", "DD"})%> 17: 18: <h1>Simple Grid with Custom Links</h1> 19: 20: <%=Html.GridView(ViewData.Model, Nothing, New GridViewOptions With {.ViewButtonText = "Look", .ShowEditButton = False, .ShowDeleteButton = False})%> 21: 22: 23: 24: </asp:Content>
Listing 2 – Index.aspx (C#)
1: <%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="Tip8.Views.Home.Index" %> 2: <%@ Import Namespace="Tip8.Helpers" %> 3: 4: <asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server"> 5: 6: <h1>Simple Grid</h1> 7: 8: <%= Html.GridView(ViewData.Model) %> 9: 10: <h1>Simple Grid without Links</h1> 11: 12: <%= Html.GridView(ViewData.Model, false) %> 13: 14: <h1>Simple Grid with Custom Headers</h1> 15: 16: <%= Html.GridView(ViewData.Model, new string[] {"AA", "BB", "CC", "DD"} )%> 17: 18: <h1>Simple Grid with Custom Links</h1> 19: 20: <%= Html.GridView(ViewData.Model, null, new GridViewOptions { ViewButtonText = "Look", ShowEditButton=false, ShowDeleteButton=false } )%> 21: 22: 23: 24: </asp:Content>
View trong Liệt kê 2 tạo ra các trang HTML được hiển thị trong Hình 1. Các trang chứa bốn grid riêng của dữ liệu (hình này chỉ cho thấy ba cái đầu tiên).
Hình 1 - Index View
![alt](https://aspblogs.blob.core.windows.net/media/stephenwalther/WindowsLiveWriter/ASP.NETMVCTip.NETMVCGridViewHelperMethod_FF6D/clip_image002_thumb.jpg)
Chú ý rằng ViewData.Model được truyền cho phương thức helper GridView(). Các ViewData.Model đại diện cho một LINQ to SQL Table. Các tập tin code-behind cho Index view chắc chắn như là một lớp System.Data.Linq.ITable. Mô hình này được thông qua để xem bởi các mã điều khiển trong Liệt kê 3.
Liệt kê 3 - HomeController.vb (VB)
1: Public Class HomeController 2: Inherits System.Web.Mvc.Controller 3: 4: Private _db As New MovieDataContext() 5: 6: Function Index() 7: Return View(_db.Movies) 8: End Function 9: End Class
Listing 3 – HomeController.cs (C#)
1: using System; 2: using System.Collections.Generic; 3: using System.Linq; 4: using System.Web; 5: using System.Web.Mvc; 6: using Tip8.Models; 7: 8: namespace Tip8.Controllers 9: { 10: public class HomeController : Controller 11: { 12: private MovieDataContext _db = new MovieDataContext(); 13: 14: public ActionResult Index() 15: { 16: return View(_db.Movies); 17: } 18: } 19: }
Tôi không hoàn toàn hài lòng với GridView() helper method đã thảo luận trong bài này. Vấn đề với việc sử dụng một phương pháp mở rộng là khá khó khăn để tùy chỉnh sự xuất hiện của các cột trong GridView. Ví dụ, tôi muốn có thể có định dạng các cột tiền tệ và ngày. Hơn thế nữa, nó sẽ được tốt đẹp nếu có một mẫu cột. Trong bài sau, tôi sẽ đưa ra một phương pháp khác, đóng gói một GridView khi làm việc với các framework ASP.NET MVC.
Bạn có thể tải mã cho phương thức helper GridView () bằng cách nhấn vào liên kết sau. Tải về bao gồm cả Visual Basic .NET và C #
[Download the Code](https://aspblogs.blob.core.windows.net/media/stephenwalther/Downloads/Tip8/Tip8.zip)
Nguồn https://weblogs.asp.net/stephenwalther/asp-net-mvc-tip-8-create-an-asp-net-mvc-gridview-helper-method