65.9K
CodeProject 正在变化。 阅读更多。
Home

GridView 一体化

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.89/5 (73投票s)

2009 年 5 月 19 日

CPOL

8分钟阅读

viewsIcon

486817

downloadIcon

10401

提供了有关使用 GridView 的清晰思路。

引言

我看到很多初学者在 GridView 上遇到困难,并且不起作用。为了在一定程度上解决这个问题,我创建了一个包含 GridView 大部分事件和属性的应用程序。这可能有助于清晰地了解如何使用 GridView。该应用程序还包含一些 JavaScript 代码片段和样式表,可用于为 GridView 添加一些值。希望本文简单易懂且足够。

什么是 GridView?

DataGridGridView 控件以表格形式显示数据,并且还支持在网格本身内选择、排序、分页和编辑数据。DataGridGridView 为数据源中的每个字段生成一个 BoundColumnAutoGenerateColumns=true)。通过直接将数据源分配给 GridView,数据可以以其在数据源中出现的顺序渲染在单独的列中。默认情况下,字段名出现在网格的列标题中,值以文本标签的形式渲染。将应用默认格式到非字符串值,并且可以更改。

GridView 字段

列名 描述
BoundColumn 用于控制列的顺序和渲染。
HyperLinkColumn 以超链接控件的形式呈现绑定的数据
ButtonColumn 将用户命令从行内冒泡到网格事件处理程序
TemplateColumn 控制在列中渲染哪些控件
CommandField 响应 DataGrid 控件的 EditItemIndex 属性的变化,显示编辑、更新和取消链接。

BoundColumn

通过在网格的 Columns 集合中显式创建 BoundColumn,可以控制每一列的顺序和渲染。在 BoundField 属性中,当给出 DataFieldSortExpression 时,可以轻松地进行排序和渲染数据。

bound.JPG

HyperLinkColumn

HyperLinkColumnHyperLink 控件的形式呈现绑定的数据。这通常用于通过直接在 NavigationUrl 中分配页面 URL 或从数据库渲染来从网格中的项导航到另一页上的详细信息视图。

Hyperlink.JPG

TemplateColumn

使用 TemplateColumn,可以控制在列中渲染的控件以及绑定到这些控件的数据字段。通过使用 TemplateColumn,可以插入任何类型的数据控件。

templete.JPG

通过单击“编辑模板”选项,可以打开模板字段,在那里我们可以看到可以添加的控件,如 LabelCheckBox,甚至 GridView

templete1.JPG

CommandField

EditCommandColumn 是一种特殊的列类型,它支持在网格的某一行中就地编辑数据。EditCommandColumn 与网格的另一个属性交互:EditItemIndex。默认情况下,EditItemIndex 的值为 -1,表示网格中的任何行(项)都未被编辑。如果 EditItemIndex 为 -1,则在网格中每一行的 EditCommandColumn 中都会显示一个“编辑”按钮。

当单击“编辑”按钮时,会触发网格的 EditCommand 事件。由程序员在代码中处理此事件。典型的逻辑是将 EditItemIndex 设置为选定的行,然后将数据重新绑定到网格。

EditItemIndex 设置为特定行时,EditCommandColumn 将为该行显示“更新”和“取消”按钮(对于其他行仍显示“编辑”)。这些按钮分别触发 UpdateCommandCancelCommand 事件。

commanfield.JPG

不同类型的事件

名称 描述
DataBinding 在服务器控件绑定到数据源时发生。(继承自 Control。)
DataBound 在服务器控件绑定到数据源之后发生。(继承自 BaseDataBoundControl。)
Disposed 在服务器控件从内存中释放时发生,这是 ASP.NET 页面请求时服务器控件生命周期的最后阶段。(继承自 Control。)
Init 在服务器控件初始化时发生,这是其生命周期的第一步。(继承自 Control。)
Load (加载) 在服务器控件加载到 Page 对象时发生。(继承自 Control。)
PageIndexChanged 当单击分页按钮之一时发生,但在 GridView 控件处理分页操作之后。
PageIndexChanging 当单击分页按钮之一时发生,但在 GridView 控件处理分页操作之前。
PreRender Control 对象加载后但在渲染之前发生。(继承自 Control。)
RowCancelingEdit 当处于编辑模式的行的 Cancel 按钮被单击时发生,但在行退出编辑模式之前。
RowCommand GridView 控件中的按钮被单击时发生。
RowCreated GridView 控件中创建行时发生。
RowDataBound GridView 控件中将数据行绑定到数据时发生。
RowDeleted 在单击行的 Delete 按钮后发生,但在 GridView 控件删除行之后。
RowDeleting 在单击行的 Delete 按钮时发生,但在 GridView 控件删除行之前。
RowEditing 在单击行的 Edit 按钮时发生,但在 GridView 控件进入编辑模式之前。
RowUpdated 在单击行的 Update 按钮后发生,但在 GridView 控件更新行之后。
RowUpdating 在单击行的 Update 按钮时发生,但在 GridView 控件更新行之前。
SelectedIndexChanged 在单击行的 Select 按钮后发生,但在 GridView 控件处理 Select 操作之后。
SelectedIndexChanging 在单击行的 Select 按钮时发生,但在 GridView 控件处理 Select 操作之前。
已排序 在单击用于排序的列的超链接后发生,但在 GridView 控件处理排序操作之后。
排序 在单击用于排序的列的超链接时发生,但在 GridView 控件处理排序操作之前。
Unload 在服务器控件从内存中卸载时发生。(继承自 Control。)

所有这些事件都列在 MSDN 上,我在这里列出了一些在我们日常项目中经常使用的事件。

PageIndexChanging

当网格的 AllowPaging 属性设置为 true 时,并且在代码隐藏中触发了 PageIndexChanging 事件。

分页

DataGrid 提供了从数据源显示一组记录(例如,前 10 条)的方法,然后导航到包含下一组 10 条记录的“页面”,依此类推。

通过将 AllowPaging 设置为 true 来启用 DataGrid 中的分页。启用后,网格将显示分页导航按钮,可以是“下一页/上一页”按钮或数字按钮。单击分页导航按钮时,会触发 PageIndexChanged 事件。由程序员在代码中处理此事件。

//AllowPaging="True"

//fires when the property AllowPaging is set to True
GridView2.PageIndex = e.NewPageIndex;
//Datasource method
TempTable();

RowCommand

当按下任何按钮时,DataGrid 会触发 RowCommand 事件。我们可以给命令名任意命名,然后根据这个名称进行检查并执行循环。

//OnRowCommand="GridView6_RowCommand"
//CommandName="view" CommandArgument='<%# Bind("id") %>'

protected void GridView6_RowCommand(object sender, GridViewCommandEventArgs e)
{
  //this will check whether the command name is equal to view. If it is
  //equal to view the it will go inside the loop.
  if (e.CommandName == "view")
  {
    //to find which row is clicked
    int row = int.Parse(e.CommandArgument.ToString());
    StringBuilder sb = new StringBuilder();
    sb.Append("<script language="'javascript'">\r\n");
    //javascript to navigate to view page.
    sb.Append(" window.open('View.aspx?id=" + row + "',
        null,'width=350,height=300,scrollbars=yes,left=350,top=200,right=5,bottom=5');");
    sb.Append("</script>");
    if (!this.IsClientScriptBlockRegistered("BindScript"))
    {
      RegisterClientScriptBlock("openScript", sb.ToString());
    }
  }
}

RowCreated

当创建新行时,DataGrid 会触发 RowCreate 事件。

//OnRowCreated="GridView3_RowCreated" 

protected void GridView3_RowCreated(object sender, GridViewRowEventArgs e)
{
  //When a child checkbox is unchecked then the header checkbox will also be unchecked.
  if (e.Row.RowType == DataControlRowType.DataRow && (e.Row.RowState == 
    DataControlRowState.Normal || e.Row.RowState == DataControlRowState.Alternate))
  {
    CheckBox chkBxSelect = (CheckBox)e.Row.Cells[1].FindControl("chkselect");
    CheckBox chkBxHeader = (CheckBox)this.GridView3.HeaderRow.FindControl("chkHeader");
    chkBxSelect.Attributes["onclick"] = string.Format("javascript:ChildClick(
        this,'{0}');", chkBxHeader.ClientID);
  }
}

RowDeleting

当命令名指定为 Delete 时,DataGrid 会触发 RowDeleting 事件。

//OnRowDeleting="GridView3_RowDeleting"
//CommandName="delete"

protected void GridView3_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
  //finding the row index of which row is selected.
  int row = e.RowIndex;
  //deleteing the temp row(or your delete query that will delete the row from
  //the database
  Temp.Rows[row].Delete();
  //reassigning the datasource
  GridView3.DataSource = Temp;
  GridView3.DataBind();
}

RowUpdating

当命令名指定为 Update 时,DataGrid 会触发 RowUpdating 事件。

//OnRowUpdating="GridView3_RowUpdating"

CommandName="update"
protected void GridView3_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
  //maintaining the row index to intial position
  GridView3.EditIndex = e.RowIndex;
  //reassigning the datasource
  GridView3.DataSource = Temp;
  GridView3.DataBind();
}

RowEditing

当命令名指定为 Edit 时,DataGrid 会触发 RowEditing 事件。

/OnRowEditing="GridView3_RowEditing"
//CommandName="edit"

protected void GridView3_RowEditing(object sender, GridViewEditEventArgs e)
{
  //changing the index of the grid.
  GridView3.EditIndex = e.NewEditIndex - 1;
  //finding the row of the grid
  int row = e.NewEditIndex;
  //updating the rows inside the grid
  Temp.Rows[row]["name"] = ((TextBox)GridView3.Rows[e.NewEditIndex].FindControl(
      "txtname")).Text;
  Temp.Rows[row]["gender"] = ((DropDownList)GridView3.Rows[e.NewEditIndex].FindControl(
      "ddlgender")).Text;
  Temp.Rows[row]["email"] = ((TextBox)GridView3.Rows[e.NewEditIndex].FindControl(
      "txtemail")).Text;
  Temp.Rows[row]["salary"] = ((TextBox)GridView3.Rows[e.NewEditIndex].FindControl(
      "txtsalary")).Text;
  Temp.AcceptChanges();
  //total of the salary and displaying it in footer.
  Total = decimal.Parse(Temp.Compute("sum(Salary)", "Salary>=0").ToString());
  //maintaining the total value in the session
  Session["Salary"] = Total;
  //reassigning the datasource
  GridView3.DataSource = Temp;
  GridView3.DataBind();
}

RowDatabound

当数据行绑定到 GridView 控件中的数据时,DataGrid 会触发 RowDatabound 事件。

//OnRowDataBound="GridView4_RowDataBound"

protected void GridView4_RowDataBound(object sender, GridViewRowEventArgs e)
{
  //Example for grid inside a grid
  //to find the row index to the selected row.
  int index = e.Row.RowIndex;
  //check whether the row type is equal
  if (e.Row.RowType == DataControlRowType.DataRow)
  {
    //assiging datasource for the grid inside the grid.
    DataTable tempdt = new DataTable();
    tempdt.Columns.Add("Id");
    tempdt.Columns.Add("Language", typeof(String));
    DataRow dr = tempdt.NewRow();
    dr["Id"] = 1;
    dr["Language"] = "C";
    tempdt.Rows.Add(dr);
    DataRow dr1 = tempdt.NewRow();
    dr1["Id"] = 2;
    dr1["Language"] = "C++";
    tempdt.Rows.Add(dr1);
    GridView gr = (GridView)(e.Row.FindControl("GridView5"));
    if (gr != null)
    {
      gr.DataSource = tempdt;
      gr.DataBind();
    }
  }
}

排序

网格中的数据通常通过单击列标题进行排序。通过将 AllowSorting 设置为 true 来启用 DataGrid 中的排序。启用后,网格会在每一列的标题中呈现 LinkButton 控件。单击按钮时,会触发网格的 SortCommand 事件。由程序员在代码中处理此事件。由于 DataGrid 始终以数据源中出现的相同顺序显示数据,因此典型的逻辑是先对数据源进行排序,然后将数据重新绑定到网格。

//AllowSorting="True"
//OnSorting="GridView2_Sorting"
//SortExpression="name"

protected void GridView2_Sorting(object sender, GridViewSortEventArgs e)
{
  //to check whether to display in ascending order or descending order
  if (e.SortExpression.Trim() == this.SortField)
    this.SortDirection = (this.SortDirection == "D" ? "A" : "D");
  else
    this.SortDirection = "A";
  this.SortField = e.SortExpression;
  TempTable();
}

网格的页眉和页脚

当需要通过选中网格标题中的单个复选框来选中列中的所有复选框时,可以使用此 JavaScript。当我们选中网格标题时,网格内的所有复选框都将被选中,并且如果任何子列被取消选中,标题也将被取消选中。

<script type="text/javascript">
var TotalChkBx;
var Counter;
window.onload = function()
{
    TotalChkBx = parseInt('<%= this.GridView3.Rows.Count %>');
    Counter = 0;
}
function SelectAll(CheckBox)
{
    var TargetBaseControl = document.getElementById('<%= this.GridView3.ClientID %>');
    var TargetChildControl = "chkselect";
    var Inputs = TargetBaseControl.getElementsByTagName("input");
    for(var n = 0; n < Inputs.length; ++n)
    if(Inputs[n].type == 'checkbox' && Inputs[n].id.indexOf(TargetChildControl,0) >= 0)
    Inputs[n].checked = CheckBox.checked;
    Counter = CheckBox.checked ? TotalChkBx : 0;
}
function ChildClick(CheckBox, HCheckBox)
{
    var HeaderCheckBox = document.getElementById(HCheckBox);
    if(CheckBox.checked && Counter < TotalChkBx)
    Counter++;
    else if(Counter > 0)
    Counter--;
    if(Counter < TotalChkBx)
    HeaderCheckBox.checked = false;
    else if(Counter == TotalChkBx)
    HeaderCheckBox.checked = true;
}
</script>
onclick="javascript:SelectAll(this);"

通过以下代码维护页脚中的值

protected void GridView3_RowDataBound(object sender, GridViewRowEventArgs e)
{
  //total in the footer
  if (e.Row.RowType == DataControlRowType.Footer)
  {
    e.Row.Cells[4].Text = this.Total.ToString();
  }
}

为了使网格标题保持固定状态,在源代码中使用了一个样式表。

<style type="text/css">.DataGridFixedHeader { 
BACKGROUND: url(Images/grid_header.jpg) repeat-x; 
POSITION: relative; TOP: expression(this.offsetParent.scrollTop); HEIGHT: 27px }

</style>
<div style="width:80%; height:250px; overflow:auto;" >
<asp:GridView ID="GridView1" runat="server" 
    Width="100%" AutoGenerateColumns="False" 
    CellPadding="4" DataKeyNames="id" 
    ForeColor="#333333" GridLines="None"
    OnRowCreated="GridView1_RowCreated" 
    AllowPaging="True" AllowSorting="True"
    OnPageIndexChanging="GridView1_PageIndexChanging" OnSorting="GridView1_Sorting"
    PageSize="2" OnRowCommand="GridView1_RowCommand"
    OnRowDeleting="GridView1_RowDeleting" 
    OnRowEditing="GridView1_RowEditing">
....
....
<HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White"
    CssClass="gridHeader DataGridFixedHeader" />
.....
.....
</asp:GridView>
</div>

将 GridView 导出到 Word、Excel 和 PDF

单词

protected void btnword_Click(object sender, EventArgs e)
{
    Response.AddHeader("content-disposition", 
                       "attachment;filename=Information.doc");
    Response.Cache.SetCacheability(HttpCacheability.NoCache);
    Response.ContentType = "application/vnd.word";
    System.IO.StringWriter stringWrite = new System.IO.StringWriter();
    System.Web.UI.HtmlTextWriter htmlWrite = new HtmlTextWriter(stringWrite);
    // Create a form to contain the grid
    HtmlForm frm = new HtmlForm();
    GridView1.Parent.Controls.Add(frm);
    frm.Attributes["runat"] = "server";
    frm.Controls.Add(GridView1);
    frm.RenderControl(htmlWrite);
    //GridView1.RenderControl(htw);
    Response.Write(stringWrite.ToString());
    Response.End();
}

Excel

protected void btnexcel_Click(object sender, EventArgs e)
{
    string attachment = "attachment; filename=Information.xls";
    Response.ClearContent();
    Response.AddHeader("content-disposition", attachment);
    Response.ContentType = "application/ms-excel";
    StringWriter sw = new StringWriter();
    HtmlTextWriter htw = new HtmlTextWriter(sw);
    // Create a form to contain the grid
    HtmlForm frm = new HtmlForm();
    GridView1.Parent.Controls.Add(frm);
    frm.Attributes["runat"] = "server";
    frm.Controls.Add(GridView1);
    frm.RenderControl(htw);
    //GridView1.RenderControl(htw);
    Response.Write(sw.ToString());
    Response.End();
}

PDF

protected void btnpdf_Click(object sender, EventArgs e)
{
    Response.Clear();
    StringWriter sw = new StringWriter();
    HtmlTextWriter htw = new HtmlTextWriter(sw);
    GridView1.RenderControl(htw);
    Response.ContentType = "application/pdf";
    Response.AddHeader("content-disposition", 
             "attachment; filename=Information.pdf");
    Response.Write(sw.ToString());
    Response.End();
}

DataGrid、DataList 和 Repeater 之间的区别

DataGridDataListRepeater 都是 ASP.NET 数据 Web 控件。

它们有很多共同点,例如 DataSource 属性、DataBind 方法以及 ItemDataBoundItemCreated 事件。

当您将 DataGridDataSource 属性分配给 DataSet 时,DataTableDataRow 集合中的每个 DataRow 都分配给一个相应的 DataGridItem,对于其他两个控件也是如此。但是,为 DataGrid 生成的 HTML 代码有一个 HTML TABLE <ROW> 元素,该元素是为特定的 DataRow 创建的,并且是以表格形式表示,包含列和行。对于 DataList,它是一个行数组,并且根据选择的模板和 RepeatColumn 属性值,我们可以指定每行 HTML <table> 中应显示多少个 DataSource 记录。简而言之,在 DataGrid 中,每行一个记录,但在 DataList 中,每行可以有五个或六个记录。对于 Repeater 控件,要显示的数据记录取决于指定的模板,生成的唯一 HTML 是由于模板而产生的。

除此之外,DataGrid 内置支持数据的排序、过滤和分页,而使用 DataList 时则不可能实现;对于 Repeater 控件,我们需要编写显式代码来实现分页。

结论

这是我的第二篇文章,如果您有任何疑问,可以参考附带的项目,因为文章中的所有代码都来自该项目。欢迎提出进一步的问题、澄清或指出错误。

© . All rights reserved.