DataGrid使用總結

 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, "");
}

發佈了52 篇原創文章 · 獲贊 0 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章