DataGruid經典技巧

來源:互聯網
上載者:User

很久以前就想寫一些關於DataGrid/DataList的東西,但是一直以來,一方面自感所學未深,另一方面,總覺無從下筆,一拖再拖,離剛開始的念頭已距一年有餘。
DataGrid/DataList在ASP.NET中的重要性,想必就不用我再強調了,凡顯示Table類型的資料,大多會使用這兩個控制項(當然,如果誰還像ASP那樣寫ASP.NET,那我也沒有辦法),所以,每個人可能都有自己的領悟,這篇文章,算是拋磚引玉,為大家做個鋪墊。

一、方法
1、DataBind
很簡單、最常用的方法。綁定資料用。需要注意的只有一點:執行了這個方法後,DataGrid(由於DataGrid和DataList極為相似,所以下面的介紹雖然是針對DataGrid,但與DataList也相差不遠)裡面所有的顯示綁定資料的控制項,都會顯示DataSource裡的資料,其餘控制項也將初始化成.aspx裡設計的狀態。

二、屬性
1、DataSource
有DataBind的地方,就應該有DataSource。如果沒有指定DataSource而執行DataBind,那DataGrid將什麼也不會顯示。
DataSource一般是DataSet、DataTable或者DataView。當然也可以綁定DataReader或者其他實現IEnumerable的類。

2、DataKeyField,DataKeys
當你在DataGrid中定位一行之後,肯定想知道這行在資料表裡的位置,至少有五種方法可以做到這一點,設定DataGrid的DataKeyField就是這幾種方法之一。
DataKeyField一般設定為資料表的Unique欄位(否則就沒意義了),通過DataKey可以得到這一行對應的關鍵字段的值。
DataKeys是DataKey的集合,通過行的索引來讀取相應行的DataKey。

3、EditItemIndex,SelectedIndex,CurrentPageIndex,SelectedItem
這些屬性都很好理解,看名字就知道是什麼意思,需要注意的是,設定了EditItemIndex或者CurrentPageIndex後需要重新執行DataBind方法(當然,前面提到過,還需要設定DataSource)。

4、Columns
沒什麼好解釋的,Columns就是Columns,列的集合,可以設定列的屬性,包括Visible、HeaderText、FooterText、SortExpression等。
嚴重注意:自動產生的列,是不包含在Columns中的。只有在.aspx中顯示聲明的列和在代碼中添加的列才會被包含在其中。

5、Items
俗話說,最後的都是最重要的,把Items作為最後一個屬性來介紹,正式基於這樣的理由。
Items是DataGridItem的集合,可以遍曆當前DataGrid中顯示資料的DataGridItem。
5.1、DataGridItem
每一個DataGridItem就是DataGrid中顯示的一行,其中包括:
Header   DataGrid 控制項的標題部分
Item   DataGrid 控制項中的項
AlternatingItem  DataGrid 控制項中的交替項
SelectedItem    DataGrid 控制項中的選定項(由SelectedIndex設定,通過SelectedItem屬性或者Items[SelectedIndex]來讀取)
EditItem    DataGrid 控制項中處於編輯狀態的項(由EditItemIndex設定,通過Items[EditItemIndex]來讀取)
Separator    DataGrid 控制項中項之間的分隔字元
Footer    DataGrid 控制項的腳註部分
Pager     DataGrid 控制項的頁選擇節
注意,DataGrid的Items屬性中不會包含Header、Footer、Pager這三類DataGridItem的。
5.1.1、DataGridItem的屬性
ItemIndex -- 得到行在Items中的索引
ItemType -- 返回行的類型,也就是上面列出的Header、Item、...、Pager
Cells -- 返回行包含的所有TableCell(不管是顯示聲明的,還是自動產生的,不管是可以看見的,還是隱藏掉的),通過TableCell,可以讀取Cell中顯示的文本、包含的控制項
嚴重注意:只有BoundColumn列和自動產生列,才可以通過TableCell.Text屬性讀取顯示的文本。HyperLinkColumn、ButtonColumn、EditCommandColumn都需要將目標控制項轉換成相應的控制項。
比如:
假設DataGrid的第一列聲明如下
<asp:HyperLinkColumn DataTextField="au_id" HeaderText="au_id" DataNavigateUrlField="au_id" DataNavigateUrlFormatString="Edit.aspx?id={0}"></asp:HyperLinkColumn>
讀取的時候可以用:
//Items[0]表示第一行,Cells[0]表示第一列,Controls[0]表示Cell中的第一個控制項(也只有這個控制項可以用)
HyperLink link = (HyperLink)DataGrid1.Items[0].Cells[0].Controls[0]);
Response.Write(link.Text);
至於模板列(TemplateColumn),當然也可以通過DataGrid1.Items[i].Cells[j].Controls[n]來擷取,然後轉換成原來的控制項類型再操作,但是還有個更好的辦法,就是用FindControl來尋找控制項。
FindControl是System.Web.UI.Control的方法,可以根據子控制項ID來尋找子控制項
比如:
假設DataGrid的某一列聲明如下
<asp:TemplateColumn>
   <ItemTemplate>
      <asp:TextBox Runat="server" ID="txtID" Text='<%# DataBinder.Eval(Container.DataItem,"au_id") %>'>
      </asp:TextBox>
   </ItemTemplate>
</asp:TemplateColumn>
讀取方法:
TextBox txt = (TextBox)DataGrid1.Items[1].FindControl("txtID");
Response.Write(txt.Text);
注意:DataList中是沒有Cell的

三、事件
1、ItemCommand、CancelCommand、DeleteCommand、EditCommand、UpdateCommand
也就是DataGrid中,點擊Button、LinkButton後執行的事件,執行的事件取決於按鈕的CommandName。其實最主要的一個是ItemCommand,而後面四個都只是ItemCommand的一小部分,
比如一個按鈕的CommandName為"Cancel",當返回後,首先執行的是ItemCommand事件,然後才是CancelCommand事件。

2、PageIndexChanged
如果你的DataGrid是分頁的,那當你在DataGrid上點擊Pager上的1、2、3或者<、>時,就會激發這個事件。
在這個事件裡面,你可以用e.NewPageIndex來讀取要改變的頁,然後賦值給DataGrid的CurrentPageIndex屬性,最後不要忘了,還要設定DataSource,還要執行DataBind。
注意:DataList中沒有這個事件,如果需要在DataList中分頁,可以一段一段的讀取資料,然後把當前段的資料繫結到DataList上。

3、ItemDataBound,ItemCreated
首先要說的是這兩個事件的發生時間。
ItemDataBound嘛,只要執行了DataBind方法,就會馬上激發這個事件。
ItemCreated呢,如果頁面是第一次訪問(Page.IsPostBack = false),那在第一次執行DataBind的時候,會先激發ItemCreated事件,也就是說,執行了DataBind後,首先會用ItemCreated來建立Header行,然後用ItemDataBound來綁定Header行,再用ItemCreated來建立第一行,再調用ItemDataBound來綁定第一行,也就是說ItemCreated和ItemDataBound是交替執行的。
頁面返回時,也會執行ItemCreated事件,在Page_Load之前,但是這時候就不會再執行ItemDataBound事件了。
所以,如果你想在DataGrid裡動態添加什麼控制項,就需要在ItemCreated事件中,而不是在ItemDataBound事件中。

四、代碼片斷
1、DataGrid顯示雙層表頭
假設你的DataGrid有三列,現在想將前兩列作為"大類1",第三列作為"大類2",現在,你可以在ItemDataBound事件中加入下面的代碼:
if (e.Item.ItemType == ListItemType.Header)
{
 e.Item.Cells[0].ColumnSpan = 2;
 e.Item.Cells[0].Text = "大類1</td><td>大類2</td></tr><tr><td>" + e.Item.Cells[0].Text;
}
用這個方法可以為任意添加新行。

2、設定繫結資料行或者自動產生列的編輯框寬度
請在你的ItemDataBound事件中加入一下代碼:
if (e.Item.ItemType == ListItemType.EditItem)
{
 for (int i = 0; i < e.Item.Cells.Count; i++)
 {
  TextBox txt = (TextBox)e.Item.Cells[i].Controls[0];
  txt.Width = Unit.Pixel(50);
 }
}

3、處理在DataGrid中的DropDownList的事件
DropDownList沒有CommandName屬性,所以不能用ItemCommand事件,不過你可以這樣試試:
在DataGrid的模板列中加入的DropDownList控制項
<asp:DropDownList runat="server" id="ddl" AutoPostBack="True" OnSelectedIndexChanged="ddl_SelectedIndexChanged" />
然後你在.aspx.cs中加入一個函數
protected void ddl_SelectedIndexChanged(object sender, System.EventArgs e) //一定要聲明成protected或者public,不能是private的。
{
  //在這裡就可以加入其他代碼
}

3.1、在上面的事件中怎樣得到本行其他Cell的值呢?
我們知道,DataGrid完全是一個Table結構的控制項,DataGrid包含DataGridItem,每個DataGridItem又包含TableCell,那麼,我們就可以在TableCell的某個控制項中,利用控制項的Parent來得到TableCell,再利用TableCell的Parent,就可以得到DataGridItem了。
protected void ddl_SelectedIndexChanged(object sender, System.EventArgs e) //一定要聲明成protected或者public,不能是private的。
{
  DropDownList ddl = (DropDownList)sender;
  TableCell cell = (TableCell)ddl.Parent;
  DataGridItem item = (DataGridItem)cell.Parent;
  Response.Write(item.Cells[0].Text);
}

4、怎樣得到Header、Footer、Pager裡的控制項
方法一:在ItemCreated或者ItemDataBound中,具體代碼就不在多寫了
方法二:遍曆DataGrid的所有Item(注意,不是遍曆DataGrid1.Items下的Item)
foreach (DataGridItem item in DataGrid1.Controls[0].Controls)
{
  if (item.ItemType == ListItemType.Header)
  {
    //用item.FindControl尋找相應的控制項
  }
}
大家可能會注意到,這裡有個DataGrid1.Controls[0].Controls,這表示,DataGrid1下,有一個子控制項,這個子控制項是DataGridTable類型,他下面才是DataGridItem集合
在DataList中,下面的子控制項直接就是DataListItem了,而沒有Table:
foreach (DataListItem item in DataList1.Controls)
{
  //....
}

 

//from msdn by lyh
Selecting Rows by Clicking Anywhere
The default model for selecting rows in the grid is for you to add a Select button (actually, a LinkButton control) whose CommandName property is set to "Select." When the button is clicked, the DataGrid control receives the Select command and automatically displays the row in selected mode.

Not everyone likes having an explicit Select button, and a common question is how to implement the feature where users can click anywhere in a grid row to select it. The solution is to perform a kind of sleight-of-hand in the grid. You add the Select LinkButton control as normal. Users can still use it, or you can hide it. In either event, you then inject some client script into the page that effectively duplicates the functionality of the Select button for the row as a whole.

The example below shows how. In the grid's ItemDataBound handler, first make sure that you are not in the header, footer, or pager. Then get a reference to the Select button, which in this instance is assumed to be the first control in the first cell. You then call a little-known method called GetPostBackClientHyperlink. This method returns the name of the postback call for the designated control. In other words, if you pass in a reference to a LinkButton control, it returns the name of the client function call that will perform the postback.

Finally, you assign the client-side method to the item itself. When the grid renders, it renders as an HTML table. By assigning the method to the item, it is the equivalent of adding client-side code to each row (<TR> element) in the table. The grid's Item object does not directly support a way to assign client code to it, but you can do that by using its Attributes collection, which passes anything you assign to it through to the browser.

Note   One small disadvantage of this technique is that it adds somewhat to the stream rendered to the browser, and it adds information for each row to view state.
' Visual Basic
Private Sub DataGrid1_ItemDataBound(ByVal sender As Object, _
      ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) _
      Handles DataGrid1.ItemDataBound
   Dim itemType As ListItemType = e.Item.ItemType
   If ((itemType = ListItemType.Pager) Or _
      (itemType = ListItemType.Header) Or _
      (itemType = ListItemType.Footer)) Then
      Return
   Else
      Dim button As LinkButton = _
         CType(e.Item.Cells(0).Controls(0), LinkButton)
      e.Item.Attributes("onclick") = _
         Page.GetPostBackClientHyperlink(button, "")
   End If
End Sub

// C#
private void DataGrid1_ItemDataBound(object sender,
System.Web.UI.WebControls.DataGridItemEventArgs e)
{
   ListItemType itemType = e.Item.ItemType;
   if ((itemType == ListItemType.Pager) ||
       (itemType == ListItemType.Header) ||
       (itemType == ListItemType.Footer))
   {
      return;
   }
   LinkButton button = (LinkButton)e.Item.Cells[0].Controls[0];
   e.Item.Attributes["onclick"] =
      Page.GetPostBackClientHyperlink(button, "");
}
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.