`

DataGrid Web 伺服器控制項的常見問題

阅读更多

作者:Visual Studio 小組
Microsoft Corporation

2002 年 1 月

摘要:回答使用 DataGrid Web 伺服器控制項的常見問題。 (共 22 頁)

適用產品

  • Microsoft® Visual Studio® .NET
  • ASP.NET
  • Web Form
  • DataGrid Web 伺服器控制項

內容

Windows Form vs. Web Form DataGrid 控制項
控制資料行寬度、高度及對齊
自訂顯示和編輯模式下的資料行配置
格式化日期、貨幣和其他資料
動態顯示和隱藏資料行
動態加入資料行
使用 DataGrid 控制項將新記錄加入資料來源
在編輯模式下顯示下拉式清單
使用核取方塊選取多重項目 (Hotmail 模型)
一次編輯多個資料列
按任何地方選取資料列

簡介

DataGrid Web 伺服器控制項是顯示資料來源之資訊的強大工具,它很容易使用,只要設定幾項屬性,就能在有專業外觀的方格中顯示可編輯資料。而且方格還有精密的物件模型,提供很大的資料顯示方式彈性。

這份文件會解答新聞群組、網站和其他開發人員討論區上常見之自訂方格顯示的相關問題,文件中說明的技術有些很簡單,有些複雜一點,但不論是哪一種情況,都能夠跨出 DataGrid 控制項之基本功能,讓您有更深的瞭解。

本文假設您已經熟悉控制項,知道如何將控制項加入表單中,設定使它顯示資料。您也應該瞭解如何將方格中的資料列變成編輯模式,以及其他的基本工作 (如需詳細資訊,請參閱〈<?XML:NAMESPACE PREFIX = MSHELP /><link tabindex="0" keywords="vbconDataGridWebControl">〉)。最後,您若是知道如何處理樣板 (將模板資料行加入方格、在樣板中配置控制項),會有很大的幫助。

Windows Form vs. Web Form DataGrid 控制項

Web Form DataGrid 控制項和 Windows Form 的等效控制項並不相同,大家通常都假設 (這算是個合理的假設) 這兩個控制項是相同的,或至少具有相同的功能。但是,Web Form 的整個程式設計範例和 Windows Form 卻是大不相同。例如,Web Form 網頁的任何處理都會執行伺服器的往返,它必須管理狀態,且資料繫結模型也不一樣等等。

由於這些差異,因此其各個控制項也有很大的差異,包括 DataGrid 控制項在內。大體而言,Web Form DataGrid 控制項的內建功能較少,以下例子即列舉 Web Form DataGrid 控制項的不同處:

  • 它本身不支援主要-詳細資料結構。
  • 它和其他 Web 伺服器控制項一樣,不支援雙向資料繫結,如果要更新資料,必須自行撰寫程式碼。
  • 一次只能編輯一個資料列。
  • 雖然它會引發事件讓您處理,以便排序方格內容,但是它本身並不支援排序。

另一方面:

  • 您可以將 Web Form DataGrid 繫結至支援 <link tabindex="0" keywords="frlrfSystemCollectionsIEnumerableClassTopic"> 介面的任何物件。
  • Web Form DataGrid 控制項支援分頁。
  • 與 Windows Form 比起來,自訂 Web Form DataGrid 控制項的外觀和配置很容易 (本文後面會提供詳細資料)。

控制資料行寬度、高度及對齊

依照預設,DataGrid 控制項會調整資料行和資料列,使其最適合您指定的方格整體高度和寬度。它會在整個方格寬度內,根據資料行標頭文字的寬度調整資料行大小,所有資料都預設為靠左顯示。

若要控制資料行特性,必須將 AutoGenerateColumns 屬性設定為 False,關閉自動產生資料行。事實上,唯有在短期使用 (例如快速概念證明頁或示範) 時,才要將這個屬性設定為 True,若是實際執行應用,您應該明確加入資料行;個別資料行可以是繫結資料行或樣板資料行。

若要設定資料行寬度,您要建立該資料行的樣式項目,然後將項目的 Width 屬性設定為標準單位 (例如像素)。以下範例顯示設定了 Width 屬性之 ItemStyle 項目的 HTML 語法。

<asp:BoundColumn DataField="title" SortExpression="title" 
      HeaderText="書名">
   <ItemStyle Width="100px"></ItemStyle>
</asp:BoundColumn>

或者可以像以下範例一樣,直接在項目中設定 ItemStyle 屬性,執行相同的工作:

<asp:BoundColumn ItemStyle-Width="100px" DataField="title" 
   SortExpression="title" HeaderText="書名">
</asp:BoundColumn>

您可以使用樣式項目設定對齊,將其設定為「Right」、「Left」和 HorizontalAlign 列舉型別中定義的其他值 (Visual Studio 中,可以在方格之屬性產生器的 [格式] 索引標籤中對齊個別的資料行)。以下就是範例:

<asp:BoundColumn DataField="title" SortExpression="title" 
      HeaderText="書名">
   <ItemStyle Width="100px" HorizontalAlign="Right"></ItemStyle>
</asp:BoundColumn>

您也可以使用樣式項目 (或 ItemStyle-Height 屬性) 設定資料行的高度。您可能會發現這不如設定寬度般有彈性,原因是設定一個資料行的高度將會同時設定所有資料行的高度。

您也可以在 Run Time 時於程式碼中設定寬度。例如 ItemCreated 事件處理常式就可以設定。以下範例會將前兩個資料行的寬度分別設定為 100 和 50 像素:

' Visual Basic
Private Sub DataGrid1_ItemCreated(ByVal sender As Object, _
    ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) _
    Handles DataGrid1.ItemCreated
        e.Item.Cells(0).Width = New Unit(100)
        e.Item.Cells(1).Width = New Unit(50)
    End Sub

// C#
private void DataGrid1_ItemCreated(object sender, System.Web.UI.WebControls.DataGridItemEventArgs e)
{
   e.Item.Cells[0].Width = new Unit(100);
   e.Item.Cells[1].Width = new Unit(50);
}

當然,在設計階段就可以設定的固定寬度,若是放在程式碼中設定,並沒有多大意義。通常唯有在您希望根據 Run Time 值設定寬度時,才要這麼做。您可以使用單位 (通常是像素) 設定儲存格或控制項的寬度,但是要將資料長度 (純粹是字元計數) 轉換為像素並不容易,不過這樣的話,在建立項目時,就有資料可供檢查。

自訂顯示和編輯模式下的資料行配置

依照預設,方格會以預先設定大小的資料行顯示資料。您將某個資料行切換為編輯模式時,不論資料屬於何種資料型別,控制項都會顯示全部可編輯資料的文字方塊。

如果您要自訂資料行的內容,請將資料行變成樣板資料行,它的作用就像 DataListRepeater 控制項中的項目樣板,只不過您定義的是資料行 (而非資料列) 的配置。

定義樣板資料行時,可以指定下列的樣板型別:

  • ItemTemplate 可以讓您自訂資料的正常顯示。
  • EditItemTemplate 可以讓您指定資料列切換為編輯模式時,資料行中顯示的內容,它除了能供您指定預設文字方塊之外,還能讓您指定控制項進行編輯的方法。
  • HeaderTemplateFooterTemplate 分別讓您自訂標頭和頁尾 (唯有方格的 ShowFooter 屬性為 True 時,才會顯示頁尾)。

以下範例示範的是顯示布林值資料之樣板資料行的 HTML 語法。ItemTemplateEditItemTemplate 都使用核取方塊來顯示值,在 ItemTemplate 中核取方塊會停用,讓使用者認為無法核取,而 EditItemTemplate 中則會啟用核取方塊。

<Columns>
<asp:TemplateColumn HeaderText="已停止">
<ItemTemplate>
   <asp:Checkbox runat="server" enabled= false name ="Checkbox2" 
     ID="Checkbox2" 
     Checked = '<%# DataBinder.Eval(Container, "DataItem.Discontinued") %>' >
   </asp:Checkbox>
</ItemTemplate>
<EditItemTemplate>
   <asp:Checkbox 
      runat="server" name ="Checkbox2" ID="Checkbox2" 
      Checked = '<%# DataBinder.Eval(Container, "DataItem.Discontinued") %>' >
   </asp:Checkbox>
</EditItemTemplate>
</asp:TemplateColumn>
</Columns>
注意如果您在 EditItemTemplate 中使用 CheckBox 控制項,請瞭解在 Run Time 時,方格儲存格除了核取方塊本身以外,實際上還包含許多 LiteralControl 控制項 (控制間距)。只要您知道控制項的值和識別碼,請使用 FindControl 方法建立其參考,而不要使用 CellsControls 集合中的特定索引:
' Visual Basic
Dim cb As CheckBox
cb = CType(e.Item.FindControl("CheckBox2"), CheckBox)

// C#
CheckBox cb;
cb = (CheckBox) e.Item.FindControl("CheckBox2");

在 Visual Studio 中,您可以使用方格的屬性產生器建立樣板資料行,並使用樣板編輯器指定配置。從方格 [屬性] 視窗頁的 [資料行] 索引標籤中選取資料行,按一下底端的 [將此資料行轉換至樣板資料行]。關閉 [屬性] 視窗,在方格上按一下滑鼠右鍵,然後選擇 [編輯樣板]。接著可以從工具箱拖曳控制項至樣板中,並加入靜態文字。

格式化日期、貨幣和其他資料

DataGrid 控制項中的資訊最後會顯示在 Web Form 網頁的 HTML 表格中,因此,若要控制資料的顯示方式,可以指定資料行值的 .NET 字串格式。您只能指定繫結或樣板資料行的格式,不能指定方格的 AutoGenerateColumns 屬性設定為 True 時產生之資料行的格式。

若要格式化,請將資料行的 DataFormatString 屬性設定為適合您要格式化之資料型別的字串格式化運算式。格式字串令人稍感困惑之處是,同一個指定元 (例如「D」) 若套用至不同資料型別 (整數、日期),就會產生不同的結果。

注意Visual Studio 中,可以在控制項屬性產生器的 [資料行] 索引標籤中指定格式運算式。

下表列出一些範例格式化字串。如需詳細資訊,請參閱 Visual Studio 文件中的<link tabindex="0" keywords="cpconFormattingTypes">〉和<link tabindex="0" keywords="frlrfSystemWebUIWebControlsBoundColumnClassDataFormatStringTopic">〉等主題。

格式運算式 適用的資料型別 說明
Price: {0:C}
注意{0} 是零,不是字母 O。
數值/十進位 顯示常值「Price:」,後接貨幣格式的數字。貨幣格式依頁面指示詞上或 Web.config 檔案中文化屬性指定的文化設定而定。
{0:D4} 整數 (不能配合十進位數使用。) 整數是在四個字元寬的零填補欄位中顯示。
{0:N2}% 數值 顯示小數位數 2 位的數字,後接常值「%」。
{0:000.0} 數值/十進位 進位到一位小數位的數字。小於三位數的數字會以零填補。
{0:D} 日期/日期時間 長日期格式 (「Thursday, August 06, 1996」)。 日期格式依頁面或 Web.config 檔案的文化設定而定。
{0:d} 日期/日期時間 短日期格式 (「12/31/99」)。
{0:yy-mm-dd} 日期/日期時間 數字式年-月-日格式的日期 (96-08-06)。

動態顯示和隱藏資料行

要讓資料行動態顯示的方法之一是在設計階段建立資料行,再視需要隱藏或顯示這些資料行,這可以利用設定資料行的 Visible 屬性做到。以下範例示範如何切換顯示方格中的第二個資料行 (index 1):

' Visual Basic
DataGrid1.Columns(1).Visible = Not (DataGrid1.Columns(1).Visible)

// C#
DataGrid1.Columns[1].Visible = !(DataGrid1.Columns[1].Visible);

動態加入資料行

如果您事先知道所需的資料行,就可以決定要隱藏或顯示資料行,不過,有時候要到 Run Time 時才會知道,這時,您可以動態建立資料行,再將其加入方格中。

您可建立方格支援之一種資料行類別 (BoundColumnEditCommandColumnButtonColumnHyperlinkColumn) 的執行個體 (您可將樣板資料行加入方格,不過這會稍微複雜一點。如需詳細資料,請參閱〈以程式建立 Web 伺服器控制項樣板〉),設定資料行的屬性,再將其加入方格的 Columns 集合。

以下範例顯示如何將兩個繫結資料行加入方格。

' Visual Basic
Private Sub Button1_Click(ByVal sender As System.Object, _
      ByVal e As System.EventArgs) Handles Button1.Click
   '設定方格的資料繫結屬性
   DataGrid1.AutoGenerateColumns = False
   DataGrid1.DataSource = Me.dsBooks1
   DataGrid1.DataMember = "Books"
   DataGrid1.DataKeyField = "bookid"

   ' 加入兩個資料行
   Dim dgc_id As New BoundColumn()
   dgc_id.DataField = "bookid"
   dgc_id.HeaderText = "識別碼"
   dgc_id.ItemStyle.Width = New Unit(80)
   DataGrid1.Columns.Add(dgc_id)

   Dim dgc_title As New BoundColumn()
   dgc_title.DataField = "title"
   dgc_title.HeaderText = "書名"
   DataGrid1.Columns.Add(dgc_title)

   Me.SqlDataAdapter1.Fill(Me.dsBooks1)
   DataGrid1.DataBind()
End Sub

// C#
private void Button1_Click(object sender, System.EventArgs e)
{
   DataGrid1.AutoGenerateColumns = false;
   DataGrid1.DataSource = this.dsBooks1;
   DataGrid1.DataMember = "Books";
   DataGrid1.DataKeyField = "bookid";

   // 加入兩個資料行
   BoundColumn dgc_id = new BoundColumn();
   dgc_id.DataField = "bookid";
   dgc_id.HeaderText = "識別碼";
   dgc_id.ItemStyle.Width = new Unit(80);
   DataGrid1.Columns.Add(dgc_id);

   BoundColumn dgc_title= new BoundColumn();
   dgc_title.DataField = "title";
   dgc_title.HeaderText = "書名";
   DataGrid1.Columns.Add(dgc_title);

   this.sqlDataAdapter1.Fill(this.dsBooks1);
   DataGrid1.DataBind();
}

任何時候將控制項動態加入網頁中,都會有保存性的問題。動態加入的控制項 (或此例中的資料行) 並不會自動加入網頁的檢視狀態,因此您必須在網頁中加入邏輯,確定資料行在每一次往返都是可用的。

最好的方法就是覆寫網頁的 LoadViewState 方法,讓您得以及早在 DataGrid 控制項中重新建立資料行。由於 LoadViewState 方法是在引發 Page_Load 事件之前就呼叫 ,因此在 LoadViewState 方法中重新加入資料行可以確保任何事件程式碼執行時,都能正常處理這些資料行。

以下範例示範如何擴充前一個範例,在每次重新執行網頁時還原資料行。和前面一樣,Button1_Click 處理常式會在方格加入兩個資料行 (在這個例子裡,事件處理常式會呼叫名為 AddColumns 的另一個常式來執行此作業)。此外,網頁還包含一個名為 DynamicColumnsAdded 的簡單布林屬性,指示方格是否有加入資料行。這個屬性在檢視狀態會一直保持其值。LoadViewState 方法先呼叫基底類別的 LoadViewState 方法,由其解壓縮檢視狀態資訊並設定其控制項。如果資料行先前已經加入方格 (利用 DynamicColumnsAdded 屬性),方法會重新加入這些資料行。

' Visual Basic
Private Property DynamicColumnAdded() As Boolean
   Get
      If ViewState("ColumnAdded") Is Nothing Then
         Return False
      Else
         Return True
      End If
   End Get
   Set(ByVal Value As Boolean)
      ViewState("ColumnAdded") = Value
   End Set
End Property

Protected Overrides Sub LoadViewState(ByVal savedState As Object)
   MyBase.LoadViewState(savedState)
   If Me.DynamicColumnAdded Then
      Me.AddColums()
   End If
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
   ' 檢查屬性,確定並未重複加入資料行
   If Me.DynamicColumnAdded Then
      Return
   Else
      Me.AddColums()
   End If
End Sub

Protected Sub AddColums()
   ' 加入兩個資料行
   Dim dgc_id As New BoundColumn()
   dgc_id.DataField = "instock"
   dgc_id.HeaderText = "現貨供應?"
   dgc_id.ItemStyle.Width = New Unit(80)
   DataGrid1.Columns.Add(dgc_id)

   Dim dgc_title As New BoundColumn()
   dgc_title.DataField = "title"
   dgc_title.HeaderText = "書名"
   DataGrid1.Columns.Add(dgc_title)
   Me.DataGrid1.DataBind()
   Me.DynamicColumnAdded = True
End Sub

// C#
private bool DynamicColumnAdded{
   get
   {
      object b = ViewState["DynamicColumnAdded"];
      return (b == null) ? false : true;
   }
   set
   {
      ViewState["DynamicColumnAdded"] = value;
   }
}

protected override void LoadViewState(object savedState) 
{
   base.LoadViewState(savedState);
   if (DynamicColumnAdded) 
   {
      this.AddColumns();
   }
}

private void Button1_Click(object sender, System.EventArgs e)
{
   if(this.DynamicColumnAdded != true)
   {
      this.AddColumns();
   }
}

private void AddColumns()
{
   BoundColumn dgc_id = new BoundColumn();
   dgc_id.DataField = "bookid";
   dgc_id.HeaderText = "識別碼";
   dgc_id.ItemStyle.Width = new Unit(80);
   DataGrid1.Columns.Add(dgc_id);

   BoundColumn dgc_title= new BoundColumn();
   dgc_title.DataField = "title";
   dgc_title.HeaderText = "書名";
   DataGrid1.Columns.Add(dgc_title);

   this.sqlDataAdapter1.Fill(this.dsBooks1);
   DataGrid1.DataBind();
   this.DynamicColumnAdded = true;
}

使用 DataGrid 控制項將新記錄加入資料來源

DataGrid 控制項能夠讓使用者檢視和編輯記錄,但是本身並不包含加入新記錄的機能,不過,您可以利用許多方式加入這項功能,主要方法如下:

  • 在方格的資料來源 (資料集或資料庫) 加入新的空白記錄,必要時,則需為記錄指定識別碼,並在不能為 Null 的任何資料行中放入替代符號值。
  • 重新繫結 DataGrid 控制項至來源。
  • 將方格切換為編輯模式來編輯新記錄。您必須要能夠決定新記錄在方格中出現的位置。
  • 在使用者按下 [更新] 後正常更新記錄,因此將新記錄和使用者提供之值一起加入來源。

以下範例顯示加入新記錄、繫結方格,然後將其切換為編輯模式的程序。在此例中,資料來源是包含「Books」這個資料表的資料集 (DsBooks1 或 dsBooks1)。

' Visual Basic
Private Sub btnAddRow_Click(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles btnAddRow.Click
   Dim dr As DataRow = Me.DsBooks1.Books.NewRow
   dr("title") = "(New)"
   dr("instock") = True
   Me.DsBooks1.Books.Rows.InsertAt(dr, 0)
   Session("DsBooks") = DsBooks1
   DataGrid1.EditItemIndex = 0
   DataGrid1.DataBind()
End Sub

// C#
private void btnAddRow_Click(object sender, System.EventArgs e)
{
   DataRow dr = this.dsBooks1.Books.NewRow();
   dr["title"] = "(New)";
   dr["instock"] = true;
   this.dsBooks1.Books.Rows.InsertAt(dr, 0);
   Session["DsBooks"] = dsBooks1;
   DataGrid1.EditItemIndex = 0;
    DataGrid1.DataBind();
}

要注意幾點:

  • 這個程式碼會在使用者按一下網頁上的 [加入] 按鈕後執行。
  • 新資料列是使用 NewRow 方法建立的,然後再用 InsertAt 方法將它插入資料集資料表,如此,您可將它放在預先定義的特定位置,在這個範例中,就是資料表中的第一筆記錄 (也就是 Rows 集合中的第一筆記錄)。或者,也可以將其加入資料表的結尾,使用資料列計數做為值。重要的是,您完全知道資料列在資料表中的位置。
  • 因為您知道記錄是在資料表中的第一個位置,所以可以將方格的 EditItemIndex 值設定為零,將新資料列切換為編輯模式 (如果是在資料表中其他位置建立資料列,可以將 EditItemIndex 改設為該位置)。
  • 由於資料集中有新的記錄 (但是資料庫中還沒有),因此必須保存一份往返間的資料集複本,畢竟您不想從資料庫中重新填入以致遺失新記錄。程式碼在此將其儲存為工作階段狀態。網頁載入時,您必須從工作階段狀態重新載入資料集。以下範例顯示您的 Page_Load 處理常式的樣子:
    ' Visual Basic
    Private Sub Page_Load(ByVal sender As System.Object, _
           ByVal e As System.EventArgs) Handles MyBase.Load
       If Me.IsPostBack Then
          DsBooks1 = CType(Session("DsBooks"), dsBooks)
       Else
          Me.SqlDataAdapter1.Fill(Me.DsBooks1)
          Session("DsBooks") = DsBooks1
          DataGrid1.DataBind()
       End If
    End Sub
    
    // C#
    private void Page_Load(object sender, System.EventArgs e)
    {
       if(this.IsPostBack)
       {
          dsBooks1 = (dsBooks) Session["DsBooks"];
       }
       else
       {
          this.sqlDataAdapter1.Fill(this.dsBooks1);
          Session["DsBooks"] = dsBooks1;
          this.DataGrid1.DataBind();
       }
    }

    如需有關維護狀態的資訊,請參閱 Visual Studio 文件中的<link tabindex="0" keywords="vbconWebFormState">〉。

  • 您可以正常更新記錄。如需範例,請參閱 Visual Studio 文件中的<link tabindex="0" keywords="vbwlkWalkthroughUsingDataGridWebControlToReadWriteData">〉。更新資料集後,請更新資料庫,然後重新整理資料集,一定要將重新整理過的資料集再次儲存為工作階段狀態。以下是更新處理常式的範例:
    ' Visual Basic
    Private Sub DataGrid1_UpdateCommand(ByVal source As Object, _
           ByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs) _
           Handles DataGrid1.UpdateCommand
       Dim dr As Dataset.BooksRow
       '取得第零列 (插入資料列的位置) 的參考
       dr = Me.DsBooks1.Books(0)
       Dim tb As TextBox = CType(e.Item.Cells(2).Controls(0), TextBox)
       dr.title = tb.Text
       Dim cb As CheckBox = CType(e.Item.Cells(3).Controls(1), CheckBox)
       dr.instock = cb.Checked
       Me.SqlDataAdapter1.Update(Me.DsBooks1)
       DataGrid1.EditItemIndex = -1
       '從資料庫重新整理資料集
       DsBooks1.Clear()
       Me.SqlDataAdapter1.Fill(Me.DsBooks1)
       '再次將重新整理過的資料集儲存為工作階段狀態
       Session("DsBooks") = DsBooks1
       DataGrid1.DataBind()
    End Sub
    
    // C#
    private void DataGrid1_UpdateCommand(object source, System.Web.UI.WebControls.DataGridCommandEventArgs e)
    {
       dsBooks.BooksRow dr;
       //取得第零列 (插入資料列的位置) 的參考
       dr = this.dsBooks1.Books[0];
       TextBox tb1 = (TextBox) e.Item.Cells[2].Controls[0];
       dr.title = tb1.Text;
       CheckBox cb = (CheckBox) e.Item.Cells[3].Controls[1];
       dr.instock = cb.Checked;
       this.sqlDataAdapter1.Update(this.dsBooks1);
       DataGrid1.EditItemIndex = -1;
       //從資料庫重新整理資料集
       dsBooks1.Clear();
       this.sqlDataAdapter1.Fill(this.dsBooks1);
       //再次將重新整理過的資料集儲存為工作階段狀態
       Session["DsBooks"] = dsBooks1;
       DataGrid1.DataBind();
    }

在編輯模式下顯示下拉式清單

資料列處理編輯模式時向使用者顯示下拉式清單是很常見的要求。例如,方格可能顯示一份書籍清單,包括每一本書的類型。使用者編輯書籍記錄時,可能要指定不同的類型。理想上,他們可以從顯示可能類型值 (例如「小說」、「傳記文學」或「參考書」) 的下拉式清單中選取。

要顯示下拉式清單,方格中必須有一個樣板資料行。通常,ItemTemplate 包含一個控制項 (例如資料繫結 Label 控制項) 以顯示記錄中某個欄位目前的值,然後您再將下拉式清單加入 EditItemTemplate。在 Visual Studio 中,您可以在方格之屬性產生器中加入樣板資料行,然後使用標準樣板編輯從 EditItemTemplate 移除預設的 TextBox 控制項,改而拖曳一個 DropDownList 控制項到其中。或者,可以在 HTML 檢視中加入樣板資料行。

建立了包含下拉式清單的樣板資料行後,接下來有兩項工作。第一項是填入清單,第二項是預先選取清單中適當的項目,例如,書本的類型若是設定為「小說」,您通常希望顯示下拉式清單時會預先選取「小說」(在所有案例下,預先選取某個項目都不會有問題)。

填入下拉式清單的方法很多,下面範例僅介紹三種方法:使用靜態項目;使用資料集中的記錄;或者使用資料讀取器直接從資料庫讀取資訊。

靜態項目

若要在下拉式清單中顯示靜態項目,不要將控制項做資料繫結,只要在控制項的 Items 集合中定義項目即可。在 Visual Studio 中,您可以從 [屬性] 視窗的 Items 屬性叫用 Items 集合。或者,可以在 HTML 檢視中加入項目。

以下是在顯示模式下顯示類型、在編輯模式下顯示類型類型靜態清單之樣板資料行的完整資料行定義。ItemTemplate 包含一個 Label 控制項,其 Text 屬性繫結至目前記錄的「類型」欄位。EditItemTemplate 中的靜態項目宣告會強調顯示。

<asp:TemplateColumn HeaderText="類型">
   <ItemTemplate>
      <asp:Label id=Label4 runat="server" 
         Text='<%# DataBinder.Eval(Container, "DataItem.genre") %>'>
      </asp:Label>
   </ItemTemplate>
   <EditItemTemplate>
      <asp:DropDownList id="DropDownList2" runat="server" Width="172px">
         <asp:ListItem Value="fiction">小說</asp:ListItem>
         <asp:ListItem Value="biography">傳記文學</asp:ListItem>
         <asp:ListItem Value="reference">參考書</asp:ListItem>
      </asp:DropDownList>
   </EditItemTemplate>
</asp:TemplateColumn>

資料集

如果要在下拉式清單中顯示的資料是在資料集中,您可以使用一般資料繫結。以下顯示的是宣告性語法。DropDownList 控制項繫結至名為 DsBooks1 之資料集中的類型資料表。資料繫結設定會強調顯示。

<asp:TemplateColumn HeaderText="類型 (資料集)">
   <ItemTemplate>
      <asp:Label id=Label3 runat="server"
          Text='<%# DataBinder.Eval(Container, "DataItem.genre") %>'>
      </asp:Label>
   </ItemTemplate>
   <EditItemTemplate>
      <asp:DropDownList id=DropDownList4 runat="server" 
         DataSource="<%# DsBooks1 %>" DataMember="Genre" 
         DataTextField="genre" DataValueField="genre" Width="160px">
      </asp:DropDownList>
   </EditItemTemplate>
</asp:TemplateColumn>

資料讀取器

您也可以直接從資料庫填入下拉式清單,這個方法雖然較為複雜,不過效率較高,因為您唯有在需要的時候,才會真正從資料庫讀取資料。

一種相對上較簡單的方法是利用 Web Form 資料繫結運算式。雖然在資料繫結運算式中最常呼叫 DataBinder.Eval 方法,不過您事實上可以呼叫網頁可用的任何公用成員。這個範例會示範如何建立一個建立、填入及傳回下拉式清單可以繫結之 DataTable 物件的函式。

在此案例中,您必須能夠執行取得您所需之記錄的資料命令。例如,您可能定義一個 CommandText 屬性為 Select * from Genres 的資料命令。 為了簡化範例,假設您的網頁上已有一個連接物件和一個資料命令物件。

首先是在網頁中建立一個公用函式,這個函式會建立一個資料表物件,並在其中定義您需要的資料行。接著開啟連接,執行資料命令以傳回資料讀取器,並透過讀取器迴圈,將資料複製到資料表。最後,將資料表當成函式的傳回值傳回。

以下範例顯示執行的方式,這個例子的傳回資料表中只有一個資料行 ("genre")。您填入下拉式清單時,通常只需要一個資料行,若是要將下拉式清單的文字和值設定至不同的資料行,則只需要兩個資料行。

' Visual Basic

Public Function GetGenreTable() As DataTable

Dim dtGenre As DataTable = New DataTable()

If Application("GenreTable") Is Nothing Then

Dim dr As DataRow

Dim dc As New DataColumn("genre")

dtGenre.Columns.Add(dc)

Me.SqlConnection1.Open()

Dim dreader As SqlClient.SqlDataReader = _

Me.SqlCommand1.ExecuteReader()

While dreader.Read()

dr = dtGenre.NewRow()

dr(0) = dreader(0)

dtGenre.Rows.Add(dr)

End While

Me.SqlConnection1.Close()

Else

dtGenre = CType(Application("GenreTable"), DataTable)

End If

Return dtGenre

End Function

//C#

public DataTable GetGenreTable()

{

DataTable dtGenre = new DataTable();

if(Application["GenreTable"] == null)

{

DataRow dr;

DataColumn dc = new DataColumn("genre");

dtGenre.Columns.Add(dc);

this.sqlConnection1.Open();

System.Data.SqlClient.SqlDataReader dreader =

this.sqlCommand1.ExecuteReader();

while(dreader.Read())

{

dr = dtGenre.NewRow();

dr[0] = dreader[0];

dtGenre.Rows.Add(dr);

}

this.sqlConnection1.Close();

}

else

{

dtGenre = (DataTable) Application["GenreTable"];

}

return dtGenre;e

}

請注意,函式將其建立的資料表快取至應用程式狀態。由於資料表是一個靜態查閱資料表,因此每次有不同資料列切換為編輯模式時,您不必重新讀取資料表。此外,因為多名使用者可以使用同一個資料表,所以您可以在全域應用程式狀態快取,而非在使用者特定工作階段狀態快取。

以下顯示的是樣板資料行的宣告。您會看到,這和繫結至資料集資料表所使用的語法很像,唯一真正的差異是 DataSource 繫結會呼叫您的函式。這種技術有一個小缺點,就是無法得到 Visual Studio 太多的設計性協助。由於您是在程式碼中定義要繫結的資料表,因此 Visual Studio 無法提供 DataMemberDataTextFieldDataValueField 屬性設定的任何選擇。您自己要確定將這些屬性設定為您在程式碼中建立之成員的名稱。

<asp:TemplateColumn HeaderText="類型 (資料庫)">
   <ItemTemplate>
      <asp:Label id=Label1 runat="server" 
           Text='<%# DataBinder.Eval(Container, "DataItem.genre") %>'>
      </asp:Label>
   </ItemTemplate>
   <EditItemTemplate>
      <asp:DropDownList id=DropDownList1 runat="server"
         DataSource="<%# GetGenreTable() %>"
         DataMember="Genre" 
         DataTextField="genre" 
         DataValueField="genre" 
         Width="120px">
     </asp:DropDownList>
   </EditItemTemplate>
</asp:TemplateColumn>

預先選取下拉式清單中的項目

您往往要設定下拉式清單中選取的項目使其符合特定值,通常是顯示模式下在儲存格中顯示的值。其方式是將下拉式清單 SelectedIndex 屬性的值設定為要顯示之值的索引。

以下範例顯示的是在 DataGrid 項目之 ItemDataBound 事件處理常式中設定的可靠方法。這是應使用的正確事件,因為不論下拉式清單使用什麼資料來源,它都可以保證已經填妥下拉式清單。

竅門是知道要將下拉式清單設定成什麼值。通常所顯示的目前項目,或者目前項目的 DataItem 屬性 (傳回包含目前記錄的 DataRowView 物件) 已經為您提供了這個值。您有了值之後,可以使用 DropDownList 控制項的 FindByTextFindByValue 方法在清單中找出正確的項目;然後可以使用項目的 IndexOf 屬性傳回索引。

' Visual Basic
Private Sub DataGrid1_ItemDataBound(ByVal sender As Object, _
      ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) _
      Handles DataGrid1.ItemDataBound
   If e.Item.ItemType = ListItemType.EditItem Then
      Dim drv As DataRowView = CType(e.Item.DataItem, DataRowView)
      Dim currentgenre As String = CType(drv("genre"), String)
      Dim ddl As DropDownList
      ddl = CType(e.Item.FindControl("DropDownList1"), DropDownList)
      ddl.SelectedIndex = ddl.Items.IndexOf(ddl.Items.FindByText(currentgenre))
   End If
End Sub

// C#
private void DataGrid1_ItemDataBound(object sender, System.Web.UI.WebControls.DataGridItemEventArgs e)
{
   if(e.Item.ItemType == ListItemType.EditItem){
      DataRowView drv = (DataRowView) e.Item.DataItem;
     String currentgenre = drv["genre"].ToString();
     DropDownList ddl = 
        (DropDownList) e.Item.FindControl("DropDownList1");
     ddl.SelectedIndex = 
         ddl.Items.IndexOf(ddl.Items.FindByText(currentgenre));
   }
}

使用核取方塊選取多重項目 (Hotmail 模型)

在 Microsoft Hotmail® 等應用程式中,使用者可以核取方塊以「選取」多個資料列,然後對所有選取的資料列執行作業 — 例如全部刪除或全部複製。

若要加入這類功能,請在方格中加入一個樣板資料行,然後在資料行中放入核取方塊。網頁執行時,使用者就能核取要使用的項目。

若要實際執行使用者動作,您可以挪動方格的 Items 集合,檢查適當的資料行 (儲存格),看看核取方塊是否已核取。以下範例顯示可以如何刪除資料集中與使用者核取之項目對應的資料列。我們假設 dsBooks1 這個資料集包含 Books 資料表。

' Visual Basic
Private Sub btnDelete_Click(ByVal sender As System.Object, _
       ByVal e As System.EventArgs) Handles btnDelete.Click
   ' 挪動方格以檢查選取的資料列
   Dim i As Integer = 0
   Dim cb As CheckBox
   Dim dgi As DataGridItem
   Dim bookid As Integer
   Dim dr As dsBooks.BooksRow
   For Each dgi In DataGrid1.Items
      cb = CType(dgi.Cells(0).Controls(1), CheckBox)
      If cb.Checked Then
         ' 決定所選記錄的索引鍵 ... 
         bookid = CType(DataGrid1.DataKeys(i), Integer)
         ' ... 取得對應之資料集記錄的指標 ..
         dr = Me.DsBooks1.Books.FindBybookid(bookid)
         ' ... 並將其刪除。
         dr.Delete()
      End If
      i += 1
   Next
   Me.SqlDataAdapter1.Update(DsBooks1)
   Me.SqlDataAdapter1.Fill(DsBooks1)
   DataGrid1.DataBind()
End Sub

// C#
private void btnDelete_Click(object sender, System.EventArgs e)
{
   int i = 0;
   CheckBox cb;
   int bookid;
   dsBooks.BooksRow dr;
   foreach(DataGridItem dgi in this.DataGrid1.Items)
   {
      cb = (CheckBox) dgi.Cells[0].Controls[1];
      if(cb.Checked)
      {
         // 決定所選記錄的索引鍵 ... 
         bookid = (int) DataGrid1.DataKeys[i];
         // ... 取得對應之資料集記錄的指標 ...
         dr = this.dsBooks1.Books.FindBybookid(bookid);
         // ... 並將其刪除。
         dr.Delete();
      }
      i++;
   }
   this.sqlDataAdapter1.Update(this.dsBooks1);
   this.sqlDataAdapter1.Fill(this.dsBooks1);
   DataGrid1.DataBind();
}

有幾點要注意:

  • 您可以使用從樣板資料行取得控制項值的標準方法,判斷核取方塊是否已經選取 — 從儲存格的 Controls 集合取得物件,並適當地轉換。如果是取得 Checkbox 控制項,請記住這通常是第二個控制項 (index 1),因為它前面有一個常值控制項 (即使是空白的)。
  • 如果是刪除,應該按照索引鍵,而非按照資料集中的位移刪除。DataGrid 控制項中某個項目的索引不一定和資料表中同一筆記錄的索引相符。即使一開始相符,等到刪除第一筆記錄後就不相符了。程式碼在此從方格的 DataKey 集合取出記錄索引鍵。然後在資料集資料表中使用 FindBy<key> 方法找出要刪除的記錄。
  • 從資料集刪除記錄後 (嚴格來說只是標記為刪除),您再呼叫資料配接器的 Update 方法將其從資料庫中刪除。接著程式碼會從資料庫重新整理資料集,並重新繫結方格。

一次編輯多個資料列

DataGrid 控制項中編輯資料列的標準方法 (加入 [編輯、更新、取消] 按鈕至方格的資料行) 只允許使用者一次編輯一個資料列。如果使用者要編輯多個資料列,必須按一下 [編輯] 按鈕,進行變更,然後為每一列按一下 [更新] 按鈕。

有時候,設定方格使其預設為編輯模式是很實用的替代方法。在此案例中,方格一律會在文字方塊或其他控制項中顯示可編輯資料;使用者不必明確地將方格切換為編輯模式。通常,使用者會進行其所要的變更,然後按一個按鈕 (不是方格中的按鈕),一次送出所有的變更。網頁看起來就像下圖:

[圖 1]

不論您是處理資料集,或者使用資料命令直接處理資料來源,任何資料模型都可以使用這種編輯方格樣式。

若要設定多列編輯的方格,請像平常一樣加入資料行,然後將所有可編輯資料行轉換為樣板資料行。在方格屬性產生器的 [資料行] 索引標籤中選取資料行,然後從視窗底端選擇 [將此資料行轉換至樣板資料行]。若要編輯樣板,請在方格上按一下滑鼠右鍵,然後選擇 [編輯樣板]。

將編輯控制項加入 ItemTemplate。請注意,因為在編輯模式下不會顯示資料列,所以您不是像平常一樣將其加入 EditItemTemplate。也就是,ItemTemplate 會包含可編輯控制項。

按平常一樣設定方格的資料繫結。您必須個別地繫結每一個可編輯控制項。典型的資料繫結運算式就像這樣:

DataBinder.Eval(Container, "DataItem.title")

載入方格和平常一樣。但是更新則有點不同,因為使用按一下 [更新] 按鈕時,您必須瀏覽整個方格,更新所有的資料列。

以下範例顯示一種可能性。此例中假設您使用的是包含參數化 SQL UPDATE 陳述式的資料命令 (dcmdUpdateBooks)。程式碼會在方格中逐個項目地從可編輯控制項展開值,再將值指定至命令參數。接著為每一個方格項目執行一次資料命令。

' Visual Basic
Private Sub btnUpdate_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnUpdate.Click
   Dim i As Integer
   Dim dgi As DataGridItem
   Dim bookid As Integer
   Dim TextBoxTitle As TextBox
   Dim CheckBoxInStock As CheckBox
   Dim TextBoxPrice As TextBox
   Dim LabelBookId as Label

   For i = 0 To DataGrid1.Items.Count - 1
       dgi = DataGrid1.Items(i)
       LabelBookId = CType(dgi.Cells(0).Controls(1), Label)
       bookid = CType(LabelBookId.Text, Integer)
       TextBoxTitle = CType(dgi.FindControl("TextBoxTitle"), TextBox)
       CheckBoxInStock = _
           CType(dgi.FindControl("CheckBoxInstock"), CheckBox)
       TextBoxPrice = CType(dgi.FindControl("TextBoxPrice"), TextBox)
       Me.dcmdUpdateBooks.Parameters("@bookid").Value = bookid
       Me.dcmdUpdateBooks.Parameters("@Title").Value = TextBoxTitle.Text
       Me.dcmdUpdateBooks.Parameters("@instock").Value = CheckBoxInStock.Checked
       Me.dcmdUpdateBooks.Parameters("@Price").Value = TextBoxPrice.Text
       Me.SqlConnection1.Open()
       Me.dcmdUpdateBooks.ExecuteNonQuery()
       Me.SqlConnection1.Close()
   Next
End Sub

// C#
private void btnUpdate_Click(object sender, System.EventArgs e)
{
   int i;
   DataGridItem dgi;
   int bookid;
   TextBox TextBoxTitle;
   CheckBox CheckBoxInStock;
   TextBox TextBoxPrice;

   for(i = 0; i <= DataGrid1.Items.Count -1 ; i++)
   {
      dgi = DataGrid1.Items[i];
      Label LabelBookId = (Label) dgi.Cells[0].Controls[1];
      bookid = int.Parse(LabelBookId.Text);
      TextBoxTitle = (TextBox) dgi.FindControl("TextBoxTitle");
      CheckBoxInStock = (CheckBox) dgi.FindControl("CheckBoxInStock");
      TextBoxPrice = (TextBox) dgi.FindControl("TextBoxPrice");
      this.dcmdUpdateBooks.Parameters["@bookid"].Value = bookid;
      this.dcmdUpdateBooks.Parameters["@Title"].Value = TextBoxTitle.Text;
      this.dcmdUpdateBooks.Parameters["@instock"].Value = CheckBoxInStock.Checked;
      this.dcmdUpdateBooks.Parameters["@Price"].Value = float.Parse(TextBoxPrice.Text);
      this.sqlConnection1.Open();
      this.dcmdUpdateBooks.ExecuteNonQuery();
      this.sqlConnection1.Close();
   }
}

檢查已變更項目

上面說明的更新策略有一個缺點,如果只有小量的變更,則傳送每一個方格資料列的更新至資料集或資料庫很沒有效率。如果是使用資料集,您可以加入邏輯,檢查方格中的控制項和資料集資料列中對應的資料行之間的變更。如果不是使用資料集 — 就像上面的範例一樣 — 就無法輕易地比較,因為會牽涉到資料庫的往返。

有一種策略同時適用於這兩種資料來源,就是建立一種判斷資料列是否「已經變更」的方法,以便在更新之前檢查。判斷資料列是否已經變更的最可靠方法,就是處理資料列中控制項的已變更事件。例如,您的方格資料列若是包含 TextBox 控制項,您可以回應控制項的 TextChanged 事件。若是核取方塊,也一樣可回應 CheckedChanged 事件。

您在這些事件的處理常式中維護一份要更新之資料列的清單。通常,最好的策略是追蹤受影響之資料列的主索引鍵。例如,您可以維護包含要更新之資料列主索引鍵的 ArrayList 物件。

想像一下上面的範例遵循此一策略。建立 ArrayList 物件的執行個體當成網頁類別的成員:

' Visual Basic
Protected bookidlist As ArrayList = New ArrayList()

// C#
protected ArrayList bookidlist = new ArrayList();

然後建立一個處理常式,只要控制項變更過,就將書籍識別碼加入 ArrayList 物件。以下程式碼顯示的是 TextBox 控制項引發其 TextChanged 事件或 CheckBox 控制項引發其 CheckedChanged 事件時,就能叫用的處理常式:

' Visual Basic
Protected Sub RowChanged(ByVal sender As Object, _
      ByVal e As System.EventArgs)
   Dim dgi As DataGridItem = _
      CType(CType(sender, Control).NamingContainer, DataGridItem)
   Dim bookidlabel As Label = CType(dgi.Cells(0).Controls(1), Label)
   Dim bookid As Integer = CType(bookidlabel.Text, Integer)
   If Not (bookidlist.Contains(bookid)) Then
      bookidlist.Add(bookid)
   End If
End Sub

// C#
protected void RowChanged( object sender, System.EventArgs e)
{
   DataGridItem dgi = (DataGridItem)(((Control)sender).NamingContainer);
   Label bookidlabel = (Label) dgi.Cells[0].Controls[1];
   int bookid = int.Parse(bookidlabel.Text);
   if (!bookidlist.Contains(bookid))
   {
      bookidlist.Add(bookid);
   }
}
注意方法不能是私用的,否則稍後將無法繫結至此方法。

瞭解變更事件預設為不會將網頁張貼回伺服器會有所幫助。唯有以其他方式張貼網頁 (通常是透過 Click 事件) 時,才會引發事件。處理網頁時,網頁及其控制項都會初始化,然後引發所有的變更事件。只有在變更事件的處理常式完成後,才會引發導致張貼的控制項 Click 事件。

上面說明的 RowChanged 方法中。程式碼必須從目前項目取得書籍識別碼。事件不會傳遞項目給您 (許多 DataGrid 事件都會傳遞),因此您必須回頭處理。從事件的 sender 引數取得 NamingContainer 屬性 (是方格項目),然後再向下切入,取得顯示書籍識別碼的 Label 控制項值。

您必須檢查確定陣列中還沒有該書籍識別碼。資料列中每一個控制項會個別引發事件,因此如果多個控制項有過變更,可能會多次將書籍識別碼加入陣列。

控制項的變更事件永遠是在 CLICK 事件之前引發和處理。因此,您可以在變更事件中建置陣列清單,而且確定在張貼表單之按一下按鈕事件處理常式 (在此例中是 btnUpdate_Click 處理常式) 執行時就能使用。

有了陣列清單後,您就可以小幅修改管理更新的處理常式。在 btnUpdate_Click中,當您重複資料方格的項目時,可加入一項測試,看看目前的書籍識別碼是否在陣列清單中。如果是,則進行更新。

' Visual Basic
Private Sub btnUpdate_Click(ByVal sender As System.Object, _
      ByVal e As System.EventArgs) Handles btnUpdate.Click
   Dim i As Integer
   Dim dgi As DataGridItem
    '其他宣告

   For i = 0 To DataGrid1.Items.Count - 1
       dgi = DataGrid1.Items(i)
       LabelBookId = CType(dgi.Cells(0).Controls(1), Label)
       If bookidlist.Contains(bookid) Then
          TextBoxTitle = CType(dgi.FindControl("TextBoxTitle"), TextBox)
          ' 其他更新程式碼
       End If
   Next
End Sub

// C#

private void btnUpdate_Click(object sender, System.EventArgs e)
{
   int i;
   DataGridItem dgi;
   int bookid;
   //其他宣告

   for(i = 0; i <= DataGrid1.Items.Count -1 ; i++)
   {
      dgi = DataGrid1.Items[i];
      TableCell tc = dgi.Cells[0];
      string s = dgi.Cells[0].Text;
      Label LabelBookId = (Label) dgi.Cells[0].Controls[1];
      bookid = int.Parse(LabelBookId.Text);
      if (bookidlist.Contains(bookid)) 
      {
         // 更新程式碼
      }
   }
}

還剩下一件工作:將處理常式繫結至控制項事件。在 Visual Studio 中,您只能在 HTML 檢視中執行這件工作。控制項並未明確地在程式碼後置 (Code-Behind) 檔案中執行個體化,因此未得到程式碼工具的支援。將 .aspx 檔案切換為 HTML 檢視,在每一個控制項的宣告性項目中加入以下強調的語法:

<asp:TemplateColumn HeaderText="書名">
   <ItemTemplate>
      <asp:TextBox OnTextChanged="RowChanged"
         id=TextBoxTitle runat="server"
         Text='<%# DataBinder.Eval(Container, "DataItem.title") %>'>
      </asp:TextBox>
   </ItemTemplate>
</asp:TemplateColumn>

<asp:TemplateColumn HeaderText="現貨供應">
   <ItemTemplate>
      <asp:CheckBox id=cbInStock OnCheckedChanged="RowChanged"
         runat="server" 
         Checked='<%# DataBinder.Eval(Container, "DataItem.instock") %>'>
      </asp:CheckBox>
   </ItemTemplate>
</asp:TemplateColumn>

TextBoxCheckBox 控制項都能從其各自的變更方法呼叫同一個方法,因為這兩個事件處理常式的簽章相同。如果您有一個清單方塊或下拉式清單控制項,其 SelectedIndexChanged 事件同樣也傳遞相同的引數,也是一樣的情形。

按任何地方選取資料列

預設的在方格中選取資料列的模型是讓您加入 CommandName 屬性設定為「選取」的 [選取] 按鈕 (實際上是 LinkButton 控制項)。按下按鈕時,DataGrid 控制項會接收選取命令,並自動以選取的模式顯示資料列。

並非每個人都喜歡有一個外顯的 [選取] 按鈕,常見的問題是如何實作功能,讓使用者能在方格資料列的任一處按一下來選取資料列。答案是在方格上耍些小花招。您如常加入 [選取] LinkButton 控制項,使用者仍然可以使用按鈕,您也可以隱藏按鈕。不論是哪一種事件,您再於網頁中插入有效地整體重複資料列 [選取] 按鈕之功能的一些用戶端指令碼。

以下範例顯示如何做。在方格的 ItemDataBound 處理常式中,先確定您不是在標頭、頁尾或頁面巡覽區,然後取得 [選取] 按鈕的參考,在此例中假設其為第一個儲存格中的第一個控制項。接著您呼叫鮮為人知的 GetPostBackClientHyperlink 方法。這個方法會傳回指定控制項的回貼呼叫名稱。換言之,您若是傳遞 LinkButton 控制項的參考,它會傳回將執行回貼之用戶端函式呼叫的名稱。

最後,您為項目本身指定用戶端方法。方格呈現時,會呈現為 HTML 表格。將方法指定至項目,就等於在資料表中每一個資料列 (<TR> 項目) 加入用戶端程式碼。方格的 Item 物件並不直接支援為其指定用戶端程式碼的方式,但是您可以使用其 Attributes 集合做到這一點,此一集合會將您指定給它的任何內容傳遞至瀏覽器。

注意這種技術有一個小缺點,就是會在呈現至瀏覽器的資料流加入一些內容,而且會將每一個資料列的資訊加入至檢視狀態。
' 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, "");
}
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics