Erstellen benutzerdefinierter Spalten für das ASP.NET Datagrid

 

Marcie Robillard
DatagridGirl.com

September 2003

Zusammenfassung: Das ASP.NET Datagrid-Steuerelements ist eines der leistungsstärkeren Steuerelemente, die dem Webentwickler zur Verfügung stehen. Erfahren Sie, wie Sie es noch leistungsfähiger machen können, indem Sie benutzerdefinierte Spalten hinzufügen, um Ihre Daten für Ihre Benutzer besser anzuzeigen. (16 gedruckte Seiten)

Gilt für:
   Microsoft® ASP.NET

Laden Sie den Quellcode für diesen Artikel herunter.

Inhalte

Einführung
Der Fall für die Wiederverwendung
Das DropDownList-Szenario
Die Built-In Datagridspalten
The Old-Fashioned Way: DropDownList in a TemplateColumn
Die Mutter aller Spalten: DataGridColumn
Die wiederverwendbare Methode: Erstellen der DropDownColumn
Verwenden von DropDownColumn
Zusammenfassung

Einführung

Das Schreiben von Datagrid-Code für Microsoft-ASP.NET® kann sich ziemlich wiederholen. Auch wenn ich von diesem Steuerelement besessen bin, suche ich immer nach Tastenkombinationen, um diese Aufgaben zu vereinfachen. Und niemand mag es, sich wiederholenden Code zu schreiben, oder? Um diese verabscheikende Aufgabe zu vermeiden, besteht das Ziel darin, Code, der sich über Projekte hinweg wiederholt, in einem schönen, zusammenhängenden Paket zu kapseln, das Sie immer wieder verwenden können. Darum geht es bei der objektorientierten Programmierung, und die Arbeit mit datagrid ist keine Ausnahme. Eine Möglichkeit, dies mit dem Datagrid-Steuerelement zu erreichen, besteht darin, Code zu verwenden, den Sie häufig mit einem der integrierten Spaltentypen verwenden würden (was ich im ersten Beispiel tun werde) und einen benutzerdefinierten Spaltentyp zu erstellen, der dann in mehreren Datagrid-Projekten wiederverwendet werden kann.

In diesem Artikel erfahren Sie, wie Sie mit einem DropDownList-Steuerelement in einer Ihrer Datagrid-Spalten mithilfe einer TemplateColumn-Standardspalte arbeiten und diese Logik dann in Ihren eigenen benutzerdefinierten Spaltentyp für das Datagrid konvertieren, den ich dropDownColumn nenne. Es gibt auch einige frei verfügbare benutzerdefinierte Datagrid-Spalten , die bereits für Sie erstellt wurden. Überprüfen Sie also, was es unter MetaBuilders.com zum Download gibt.

Der Fall für die Wiederverwendung

Wenn Ihre Gruppe wie viele andere Organisationen ist, haben Sie Ihre Geschäftslogik und/oder Datenzugriffslogik bereits in eine separate Komponente oder einen Satz von Komponenten aufgeteilt, und die verbleibenden ASP.NET Dateien, ASPX und CodeBehind enthalten reine Präsentationslogik. ("Rein" ist ein relativer Begriff.) Selbst diese Logik auf Präsentationsebene sollte jedoch nach Möglichkeit wiederverwendet werden, sodass Sie schnell etwas erstellen können, wenn ein Benutzer das nächste Mal kommt und an Ihre Tür klopft und sagt: "Hey, ich möchte, dass meine Anwendung genauso aussieht wie Susie in der Buchhaltung", sie schnell etwas erstellen und einige der Präsentationselemente aus der Buchhaltungsanwendung wiederverwenden. Oder Vielleicht möchten Sie eine Logik packen, um im Web zu verkaufen oder auf Ihrer Website zu verteilen. ASP.NET macht dies einfacher als je zuvor, da Sie ihre eigenen Serversteuerelemente erstellen oder von vorhandenen Typen ableiten können, um die benötigten Funktionen zu erhalten.

Das DropDownList-Szenario

Angenommen, Sie bearbeiten die Northwind-Datenbank auf Ihrem lokalen Microsoft SQL Server ™, und Sie möchten Ihrem Benutzer (nennen wir ihn Ed the Fulfillment Manager) die Möglichkeit geben, die Tabelle Orders zu bearbeiten. Eines der Felder enthält die Versandinformationen (ShipVia), die Ed ändern können muss. Im Anzeigemodus sollte das Versandunternehmen als Nur-Text angezeigt werden. Wenn Ed auf die Schaltfläche Bearbeiten klickt, anstatt ihm nur ein TextBox-Element zum Bearbeiten des Versandmethodencodes (1, 2 oder 3) bereitzustellen, möchten Sie ihm eine DropDownList mit den verschiedenen Versandunternehmen geben, aus denen er wählen kann. (Ed kann sich nicht erinnern, welches Versandunternehmen welcher Nummer entspricht, also hilft ihm das.)

Aa479316.creatingcustomcolumns_fig1(en-us,MSDN.10).gif

Abbildung 1. Auswählen eines Versandunternehmens

Die Built-In Datagridspalten

Nachdem wir nun die Problemsituation überprüft haben, gehen wir einen Schritt zurück und sehen uns die fünf Spaltentypen für Datagrid-Spalten an, die in ASP.NET integriert sind, und deren übergeordnete Klasse, DataGridColumn.

  • BoundColumn. Dies ist für die Standardanzeige von Textfeldern vorgesehen. Es wird als Nur-Text gerendert, wird aber in ein TextBox-Objekt konvertiert, wenn das Datagrid in den Bearbeitungsmodus versetzt wird. Einige Formatierungsoptionen sind ebenfalls verfügbar.
  • HyperlinkColumn. Dies ist für die Anzeige von Textdaten vorgesehen, die auch eine Webadresse (URL) darstellen. Die URL ist möglicherweise identisch mit dem Anzeigetext. Beide können unabhängig voneinander festgelegt werden. Es wird als <href=...> -Tag gerendert.
  • ButtonColumn. Dies dient dazu, die Benutzerinteraktion mit dem Raster auf Zeilenbasis zuzulassen. Sie kann entweder als LinkButton-LinkButton (<href=...>) oder als Pushbutton (<input type="button">) gerendert werden. Ein PostBack wird ausgelöst, wenn auf die Schaltfläche geklickt wird, und das ItemCommand-Ereignis wird im Datagrid ausgelöst.
  • EditCommandColumn. Dies ähnelt ButtonColumn, erstellt aber automatisch Schaltflächen zum Bearbeiten des Datagrids und zum Abbrechen oder Übermitteln der vorgenommenen Änderungen. Löst das ItemCommand-Ereignis sowie das spezifische Ereignis für die Schaltfläche aus, auf die geklickt wurde, EditCommand, CancelCommand oder UpdateCommand.
  • TemplateColumn. Dies dient der vollständigen Kontrolle darüber, welche Steuerelemente dem Benutzer angezeigt werden, unterteilt in verschiedene Vorlagen, z. B . ItemTemplate und EditItemTemplate. Jedes ASP.NET- oder HTML-Steuerelement oder eine Gruppe von Steuerelementen kann in diesen Vorlagen platziert werden.

Hinweis Bevor Sie mit diesen Spaltentypen direkt arbeiten, deaktivieren Sie "Automatisches Generieren von Spalten zur Laufzeit" (AutoGenerateColumns). Anschließend können Sie mit diesen Spaltentypen entweder im Eigenschaften-Generator oder direkt im HTML-Code Ihrer ASPX-Datei arbeiten.

Aa479316.creatingcustomcolumns_fig2(en-us,MSDN.10).gif

Abbildung 2. Fünf integrierte Spalten, geerbt von DataGridColumn

So nützlich diese Spaltentypen auch sind, sie sind nur der Anfang dessen, was in einer Datagrid-Spalte möglich ist.

The Old-Fashioned Way: DropDownList in a TemplateColumn

Bevor Sie sich mit der Erstellung des neuen Spaltentyps befassen, sehen wir uns zunächst an, wie Sie das Dropdownproblem ohne benutzerdefinierte Spalte lösen, indem Sie direkt in einer TemplateColumn mit einer DropDownList arbeiten. Die ItemTemplate enthält nur die Nur-Text-Darstellung des aktuellen Werts, während EditItemTemplate ein <asp:DropDownList-Steuerelement> enthält, das Sie zur Laufzeit bearbeiten.

<asp:DataGrid id="DataGrid1" 
   runat="server" CssClass="grid" 
   AutoGenerateColumns="False">
   <Columns>
      <asp:EditCommandColumn 
         EditText="Edit" CancelText="Cancel" 
         UpdateText="Update" />
      <asp:BoundColumn 
         DataField="OrderID" ReadOnly="True" 
         HeaderText="Order ID" />
      <asp:BoundColumn 
         DataField="ShipName" HeaderText="Ship to" 
         ReadOnly="True" />
      <asp:BoundColumn 
         DataField="ShipCountry" HeaderText="Country" 
         ReadOnly="True" />
      <asp:TemplateColumn HeaderText="Ship Method">
         <ItemTemplate>
            <%#Container.DataItem("ShipVia")%>
         </ItemTemplate>
         <EditItemTemplate>
            <asp:DropDownList runat="server" ID="Dropdownlist1"/>
         </EditItemTemplate>
      </asp:TemplateColumn>
   </Columns>
</asp:DataGrid>

Code zum Binden des Datagrids:

Sub BindGrid()
    Dim SQL As String = "SELECT OrderID, 
      ShipName, ShipCountry, ShipVia FROM Orders"
    Dim DA As SqlDataAdapter = New SqlDataAdapter(SQL, ConnStr)
    Dim DS As New DataSet
    DA.Fill(DS, "Orders")
    DataGrid1.DataSource = DS.Tables("Orders").DefaultView
    DataGrid1.DataBind()
End Sub

Die Bindung der DropDownList für das Element, das gerade bearbeitet wird, erfolgt während des ItemDataBound-Ereignisses des Datagrids. Wenn Sie das ItemDataBound-Ereignis verwenden, überprüfen Sie immer den ListItemType des aktuellen Elements, oder Sie können schnell feststellen, dass Sie mit einem HeaderItem oder einem anderen nicht anwendbaren Elementtyp arbeiten. Rufen Sie einen Verweis auf das DropDownList-Steuerelement für das EditItem ab. Im folgenden Code habe ich dies mithilfe der Steuerelementsammlung der Zelle direkt gezeigt (aus Gründen der Konsistenz mit späteren Beispielen), aber Sie können dies genauso einfach tun, indem Sie dem DropDownList-Steuerelement eine ID zuweisen und den Steuerelementverweis mithilfe der FindControl-Methode des Datagrid-Elements suchen. Da das Datagrid an die Standardansicht einer DataTable gebunden ist, ist jedes Element dieser Ansicht vom Typ DataRowView, und Sie können die DataItem-Eigenschaft des aktuellen Elements in eine instance von DataRowView umwandeln. Dadurch können Sie auf Felder in diesem DataItem direkt anhand ihres Feldnamens verweisen. Speichern Sie mit dieser Technik den aktuellen Wert für "ShipVia" in diesem Datensatz, und wählen Sie damit das entsprechende Dropdownelement aus.

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 CurrentShip As String = DRV("ShipVia")
        Dim DDL As DropDownList = _
      CType(e.Item.Cells(4).Controls(1), DropDownList)
        Dim SQL As String = _
      "SELECT ShipperID, CompanyName FROM Shippers ORDER BY ShipperID"
        Dim DA As SqlDataAdapter = New SqlDataAdapter(SQL, ConnStr)
        Dim DS As New DataSet
        Dim item As ListItem
        DA.Fill(DS, "Shippers")
        DDL.DataSource = DS.Tables("Shippers").DefaultView
        DDL.DataTextField = "CompanyName"
        DDL.DataValueField = "ShipperID"
        DDL.DataBind()
        item = DDL.Items.FindByValue(CurrentShip)
        If Not item Is Nothing Then item.Selected = True
    End If
End Sub

Und schließlich der Code, um den aktuell ausgewählten Wert aus der DropDownList abzurufen und das Update zurück in die Datenbank auszuführen:

Private Sub DataGrid1_UpdateCommand(ByVal source As Object, _
   ByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs) _
   Handles DataGrid1.UpdateCommand
    Dim DDL As DropDownList = _
      CType(e.Item.Cells(4).Controls(1), DropDownList)
    Dim NewShip As Integer = DDL.SelectedValue
    Dim OrderID As Integer = Int32.Parse(e.Item.Cells(1).Text)
    Dim SQL As String = _
      "UPDATE Orders SET ShipVia=@Ship WHERE OrderID=@ID"
    Dim Conn As SqlConnection = New SqlConnection(ConnStr)
    Dim Cmd As New SqlCommand(SQL, Conn)
    Cmd.Parameters.Add(New SqlParameter("@Ship", NewShip))
    Cmd.Parameters.Add(New SqlParameter("@ID", OrderID))
    Conn.Open()
    Cmd.ExecuteNonQuery()
    Conn.Close()
    DataGrid1.EditItemIndex = -1
    BindGrid()
End Sub

Die Mutter aller Spalten: DataGridColumn

Gehen wir zurück und untersuchen die übergeordnete Klasse aller integrierten Spaltentypen DataGridColumn. (Siehe Abbildung 1.) Sie enthält die Eigenschaften und Methoden, die für alle Datagrid-Spalten gemeinsam sind. Ich habe neben den star, die Sie in Ihrem benutzerdefinierten Spaltentyp verwenden, den Sie erstellen werden, platziert.

DataGridColumn-Eigenschaften

  • FooterStyle (TableItemStyle)
  • FooterText (String)
  • HeaderImageUrl (String)
  • HeaderStyle (TableItemStyle)
  • HeaderText (String)
  • ItemStyle (TableItemStyle)
  • SortExpression (String)
  • Visible (Boolean)

DataGridColumn-Methoden

  • Initialisieren
  • Initializecell
  • Loadviewstate
  • OnColumnChanged
  • Saveviewstate
  • Trackviewstate

Die wiederverwendbare Methode: Erstellen der DropDownColumn

Als Erstes müssen Sie ein neues Klassenbibliotheksprojekt in Microsoft® Visual Studio® .NET erstellen und es MyCustomColumn nennen. Fügen Sie eine neue Klasse mit dem Namen DropDownColumn hinzu, und stellen Sie sicher, dass Sie den Namespace um Ihre Klassendefinition herum hinzufügen, damit Ihr anfänglicher Code wie folgt aussieht:

Namespace MyCustomColumn
    Public Class DropDownColumn
        Inherits DataGridColumn

        Public DataSource As ICollection
        Public DataField As String
        Public DataTextField As String
        Public DataValueField As String

    End Class
End Namespace

Ich habe auch 4 öffentliche Eigenschaften deklariert, die wie folgt verwendet werden sollen:

  • DataSource: Dies ist der Satz von Daten, die die DropDownList auffüllen sollen. Dies kann alles sein, was die ICollection-Schnittstelle implementiert. Für die in diesem Artikel gezeigten Beispiele verwende ich eine ArrayList und eine DataView.
  • DataField. Dies ist das Feld in der Datenquelle des übergeordneten Datagrids, das den daten entspricht, die in der Dropdownliste ausgewählt werden sollen. Wenn die DataSource z. B. eine Auflistung von Zuständen enthält, wäre DataField in etwa "StateCode" oder ein beliebiger Name des Felds in der Tabelle mit den Zuständen.
  • DataTextField. Dies ist der Text, der in der Dropdownliste angezeigt werden soll, der dem zugrunde liegenden Wert entspricht oder nicht.
  • DataValueField. Dies ist der Wert, der eine bestimmte Dropdownauswahl darstellt. Das DataValueField ist häufig ein ganzzahliger Wert oder ein anderer Code, während DataTextField die Textbeschreibung ist, die für den Benutzer aussagekräftiger ist.

Als Nächstes überschreiben Sie InitializeCell, eines der inhärenten Ereignisse der Datagrid-Spalte . InitializeCell tritt für jede Tabellenzelle in der Spalte auf, ähnlich wie das ItemCreated-Ereignis beim direkten Arbeiten mit dem Datagrid . Hier können Sie den Zellinhalt bearbeiten, z. B. den HeaderText festlegen und das DropDownList-Steuerelement hinzufügen, dem Sie Ihre Daten hinzufügen. Ich habe auch Handler für das DataBinding-Ereignis der Zelle hinzugefügt, das je nachdem, ob die Zeile gerade bearbeitet wird, unterschiedlich verarbeitet werden muss. Jedes System.Web.UI.Control-Ereignis verfügt über ein DataBinding-Ereignis , und hier erhalten Sie Zugriff auf die zugrunde liegenden Daten, da die Daten an ein Steuerelement gebunden werden, in diesem Fall ein TableCell-Objekt in einem Datagrid.

Public Overrides Sub InitializeCell(ByVal cell As TableCell, _
   ByVal columnIndex As Integer, _
   ByVal itemType As ListItemType)
       MyBase.InitializeCell(cell, columnIndex, itemType)
       Select Case itemType
              Case ListItemType.Header
                   cell.Text = HeaderText
              Case ListItemType.Item, ListItemType.AlternatingItem
                   AddHandler cell.DataBinding, AddressOf ItemDataBinding
              Case ListItemType.EditItem
                   AddHandler cell.DataBinding, AddressOf EditItemDataBinding
                   Dim DDL As New DropDownList
                   cell.Controls.Add(DDL)
            End Select
        End Sub

Als Nächstes wird die ItemDataBinding-Routine ausgelöst, die ausgelöst wird, wenn jedes Item- oder AlternatingItem-Element im Datagrid datengebunden ist. Hier müssen Sie einen Verweis zurück auf die tableCell abrufen, die gebunden wird. Dies können Sie als direkte Umwandlung des an das Ereignis übergebenen "sender"-Objekts ausführen. Außerdem müssen Sie mithilfe der NamingContainer-Eigenschaft von TableCell einen Verweis auf das aktuelle DataGridItem-Objekt abrufen. Von dort aus können Sie den Inhalt von DataField einfach als Nur-Text anzeigen, genau wie es der Fall wäre, wenn dieses Feld in einer BoundColumn-Spalte angezeigt würde. Schließlich möchte ich dem Benutzer eine freundlichere Fehlermeldung geben, wenn das angegebene Feld nicht vorhanden ist; Andernfalls erhalten sie nur die generische Meldung "Index was out of range".

Private Sub ItemDataBinding(ByVal sender As Object, ByVal e As EventArgs)
     Dim cell As TableCell = CType(sender, TableCell)
     Dim DGI As DataGridItem = CType(cell.NamingContainer, DataGridItem)
     Try
          cell.Text = DGI.DataItem(DataField)
     Catch RangeEx As IndexOutOfRangeException
          Throw New Exception("Specified DataField was not found.")
     Catch OtherEx As Exception
          Throw New Exception(OtherEx.InnerException.ToString)
     End Try
 End Sub
 

Als Nächstes codieren Sie das EditItemDataBinding-Ereignis , das in der Zelle unserer benutzerdefinierten Spalte geschieht, wenn eine Zeile in den Bearbeitungsmodus wechselt. Rufen Sie erneut einen Verweis auf die aktuelle Zelle und das DropDownList-Steuerelement ab, das während der InitializeCell-Methode eingefügt wurde. Fügen Sie ein leeres Element als erste Auswahl in der DropDownList hinzu, das ausgewählt wird, wenn die daten, die derzeit in der Spalte enthalten sind, nicht mit den Elementen übereinstimmen, die Sie in der Liste aus der DataSource-Auflistung platzieren.

Anschließend müssen Sie den Typ der übergebenen Sammlung bestimmen. Für die Zwecke dieses Beispiels werde ich zwei Fälle behandeln, einen Satz von Zeichenfolgen, die über eine ArrayList übergeben werden, oder eine DataView aus einer Datentabelle, die aus DataRowView-Elementen besteht. Für Zeichenfolgendaten gebe ich ein neues ListItem ein und setz sowohl den Wert als auch den Text des Dropdownelements. Der Text ist hier alles, was wirklich benötigt wird, da die beiden identisch sind, aber ich wähle das entsprechende Element aus, das basierend auf dem Wert ausgewählt werden soll, um das nächste Beispiel zu berücksichtigen, das eine separate Werteigenschaft festlegt. Für DataRowView-Elemente habe ich im vorherigen Beispiel bemerkt, dass DataRowViewInstance("FieldName") ein Objekt zurückgibt, das die Daten für dieses Feld darstellt. Der gleiche Ansatz kann verwendet werden, um die für DataTextField und DataValueFields erforderlichen Werte abzurufen.

Lösen Sie schließlich einige Ausnahmen aus, um häufige Fehler zu behandeln, die Entwickler bei der Verwendung dieser Spalte machen könnten, z. B. das Senden eines ungültigen Feldnamens in der DataField-Eigenschaft oder das Übergeben eines inkompatiblen DataSource-Typs . Ich habe die Ausnahmemeldungen hartcodiert, um nach oben zu blasen, aber hoffentlich würden Sie diese in einer echten Anwendung an einem besser konfigurierbaren Ort speichern, z. B. in Ihrer web.config-Datei oder in einer Ressourcendatei, wenn Sie Ihre Anwendung globalisieren möchten. Außerdem müssen Sie die Ausnahme "Angegebenes DataField wurde nicht gefunden" hier nicht erneut auslösen, da es bereits im ItemDataBinding-Ereignis erfasst worden wäre, bevor das Datagrid jemals in den Bearbeitungsmodus versetzt wird.

Private Sub EditItemDataBinding(ByVal sender As Object, _
ByVal e As EventArgs)
            Dim cell As TableCell = CType(sender, TableCell)
            Dim DDL As DropDownList = _
CType(cell.Controls(0), DropDownList)
            Dim DataSourceItem As Object
            Dim item As ListItem
            Dim DGI As DataGridItem

            'Add a first, blank option
            DDL.Items.Add(New ListItem(""))
            For Each DataSourceItem In DataSource
                Select Case DataSourceItem.GetType.ToString
                    Case "System.String" 'Applies to ArrayList example
                        item = New ListItem(DataSourceItem, DataSourceItem)
                        DDL.Items.Add(item)
                    Case "System.Data.DataRowView"
                        Dim DRV As DataRowView = _
                           CType(DataSourceItem, DataRowView)
                        item = New_
              ListItem(DRV(DataTextField), DRV(DataValueField))
                        DDL.Items.Add(item)
                    Case Else
                        Throw New Exception("Invalid DataSource type.")
                End Select
            Next

            Try
                DGI = CType(cell.NamingContainer, DataGridItem)
                item = DDL.Items.FindByValue(DGI.DataItem(DataField))
            Catch RangeEx As IndexOutOfRangeException
                Throw New Exception("Specified DataField was not found.")
            Catch OtherEx As Exception
                Throw New Exception(OtherEx.InnerException.ToString)
            End Try

            If Not item Is Nothing Then item.Selected = True
End Sub

Verwenden von DropDownColumn

Nachdem Sie nun den gesamten Code gesehen haben, der zum Erstellen der DropDownColumn-Klasse erforderlich ist, sehen wir uns an, was erforderlich ist, um dieses Steuerelement in einer Anwendung zu verwenden. Wenn Sie zu Hause folgen und dies noch nicht getan haben, erstellen Sie den oben erstellten Namespace in MyCustomColumn.dll, und kopieren Sie ihn in den Ordner /bin einer Anwendung, in der Sie ihn ausprobieren möchten. Für meine Zwecke habe ich eine neue Webanwendung namens UseCustomColumn erstellt und einen Verweis auf die MyCustomColumn.dll in meinem Verzeichnis /bin hinzugefügt. Fügen Sie am Anfang einer ASPX-Datei die @Register -Anweisung hinzu:

<%@ Register TagPrefix="dgg" 
      Namespace="MyCustomColumn" 
      Assembly="MyCustomColumn" %>

Beachten Sie, dass der neue Datagrid-Spaltentyp nicht im Visual Studio .NET-Eigenschaften-Generator für das Datagrid angezeigt wird, sodass Sie in die HTML-Ansicht wechseln und dort die Spaltendeklaration hinzufügen müssen. Stellen Sie sicher, dass sich die Datagrid-Deklaration innerhalb einer Gruppe der <Form runat="server">... befindet.</form-Tags> , die für die Verarbeitung der PostBacks benötigt werden. Der Rest der ASPX-Datei sieht wie folgt aus:

<%@ Page Language="vb" 
   AutoEventWireup="false" 
   Codebehind="WebForm1.aspx.vb" 
   Inherits="UseCustomColumn.WebForm1" 
Trace="False" Debug="True"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
   <HEAD>
      <title>WebForm1</title>
      <LINK rel="stylesheet" type="text/css" href="Styles.css">
      <meta name="GENERATOR" content="Microsoft Visual Studio.NET 7.0">
      <meta name="CODE_LANGUAGE" content="Visual Basic 7.0">
      <meta name="vs_defaultClientScript" content="JavaScript">
      <meta name="vs_targetSchema" 
         content="https://schemas.microsoft.com/intellisense/ie5">
   </HEAD>
   <body>
   <form id="Form1" method="post" runat="server">
   <asp:DataGrid id="DataGrid1" 
      runat="server" CssClass="grid" 
      AutoGenerateColumns="False">
      <Columns>
         <asp:EditCommandColumn 
            EditText="Edit" CancelText="Cancel" 
            UpdateText="Update" />
         <asp:BoundColumn 
            DataField="OrderID" 
            ReadOnly="True" 
            HeaderText="Order ID"/>
         <asp:BoundColumn 
            DataField="ShipName" 
            HeaderText="Ship to" 
            ReadOnly="True"/>
         <asp:BoundColumn 
            DataField="ShipCountry" 
            HeaderText="Country" 
            ReadOnly="True"/> 
         <dgg:DropDownColumn DataField="ShipVia" HeaderText="Ship Method" />
      </Columns>
   </asp:DataGrid>
   </form>
   </body>
</HTML>

Das Datagrid ist an die Tabelle Orders im Northwind-Beispiel gebunden, und das benutzerdefinierte DropDownColumn ist an die Spalte ShipVia gebunden. Vorerst werde ich nur die DataField-Eigenschaft festlegen, da ich nur an eine einfache ArrayList gebunden bin und die Eigenschaften DataTextField und DataValueField nicht benötigt werden. Die Option ArrayList ist am einfachsten, wenn Sie über eine vordefinierte Liste nicht ändernder Daten verfügen oder eine Quick-and-modifiziert-Methode zum Festlegen von Optionen verwenden möchten. Die DataSource für dropDownColumn wird im Code festgelegt und erhält zunächst einen Verweis auf dropDownColumn:

Dim DDC As MyCustomColumn.DropDownColumn
DDC = CType(DataGrid1.Columns(4), MyCustomColumn.DropDownColumn)
 Dim AL As New ArrayList
 AL.Add("Shipping Company A")
 AL.Add("Shipping Company B")
 AL.Add("Shipping Company C")
 DDC.DataSource = AL

Und hier ist die Ausgabe, wenn Sie folgendes ausführen:

Aa479316.creatingcustomcolumns_fig3(en-us,MSDN.10).gif

Abbildung 3. Verwenden einer ArrayList

Als Nächstes muss ich dieses Beispiel konvertieren, um eine Livetabelle aus der Datenbank zu verwenden. ShipVia ist ein Fremdschlüssel zur Nachschlagetabelle "Shippers", die ich unserer DropDownColumn im Code als Datenquelle zuweisen werde. Außerdem muss ich die Deklaration von DropDownColumn ändern, um die Namen DataTextField und DataValueField einzuschließen, die den entsprechenden Feldern in der Tabelle Shippers entsprechen:

<dgg:DropDownColumn 
   DataField="ShipVia" 
   DataTextField="CompanyName" 
   DataValueField="ShipperID" HeaderText="Ship Method" />

Binden Sie dann sowohl die Tabelle Orders an das Datagrid als auch die Tabelle Shippers an die benutzerdefinierte Spalte:

     Dim SQL As String = 
     "SELECT OrderID, ShipName, ShipCountry, ShipVia FROM Orders"
        Dim DA As SqlDataAdapter = New SqlDataAdapter(SQL, ConnStr)
        Dim DS As New DataSet
        DA.Fill(DS, "Orders")
        'Dim Cmd As SqlCommand = New SqlCommand(SQL, Conn)
        'Conn.Open()
        'DataGrid1.DataSource = _
      Cmd.ExecuteReader(CommandBehavior.CloseConnection)
        DataGrid1.DataSource = DS.Tables("Orders").DefaultView
        SQL = "SELECT ShipperID, CompanyName " & _
            "FROM Shippers ORDER BY ShipperID"
        DA.SelectCommand.CommandText = SQL
        DA.Fill(DS, "Shippers")
        DDC.DataSource = DS.Tables("Shippers").DefaultView
        DataGrid1.DataBind()

Bei den Livedaten wählt dataGridColumn automatisch das richtige Element aus der DropDownList basierend auf dem Wert (1, 2 oder 3) in der Tabelle Orders aus, wie folgt:

Aa479316.creatingcustomcolumns_fig4(en-us,MSDN.10).gif

Abbildung 4. Abrufen von Daten aus der Datenbank

Der letzte Schritt bei der Verwendung von DropDownColumn ist das Abrufen des ausgewählten Werts, der an die Aktualisierung der Datenbank zurückgegeben wird. Rufen Sie dazu einfach einen Verweis auf das DropDownList-Steuerelement in der Zelle ab, und bestimmen Sie dessen SelectedValue-Eigenschaft :

 Private Sub DataGrid1_UpdateCommand( _
   ByVal source As Object, _
   ByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs) _
   Handles DataGrid1.UpdateCommand
        Dim CustomDDL As DropDownList = _
CType(e.Item.Cells(4).Controls(0), DropDownList)
        Dim NewShip As Integer = CustomDDL.SelectedValue
        Dim OrderID As Integer = Int32.Parse(e.Item.Cells(1).Text)
        Dim SQL As String = _
         "UPDATE Orders SET ShipVia=@Ship WHERE OrderID=@ID"
        Dim Conn As SqlConnection = New SqlConnection(ConnStr)
        Dim Cmd As New SqlCommand(SQL, Conn)
        Cmd.Parameters.Add(New SqlParameter("@Ship", NewShip))
        Cmd.Parameters.Add(New SqlParameter("@ID", OrderID))
        Conn.Open()
        Cmd.ExecuteNonQuery()
        Conn.Close()
        DataGrid1.EditItemIndex = -1
        BindGrid()
    End Sub

Zusammenfassung

Hier erfahren Sie, wie Sie einen neuen Spaltentyp erstellen, der von DataGridColumn abgeleitet wird, wie Sie die Datenbindung nutzen, während dies geschieht, und das Objekt in einer echten Anwendung verwenden. Dies ist nur ein Beispiel für eine wiederverwendbare Datagrid-Spalte , und daher besteht meine Herausforderung an Sie darin, Ihre eigenen Anwendungen zu untersuchen, um zu sehen, welche Funktionen Sie wiederholen, die sauber in eine eigene benutzerdefinierte Datagrid-Spalte eingeschlossen werden könnten. Entwickeln Sie eigene Spalten für gängige Verwendungsszenarien wie dropDownList in einer Spalte oder mit speziellen Funktionen, die für Ihre organization. Sie müssen sich auch nicht einschränken, indem Sie nur ein ASP.NET Steuerelement in Ihre benutzerdefinierte Spalte einfügen. Sie können komplexere Strukturen erstellen, z. B. eine Reihe anderer Steuerelemente, Inhalte von Drittanbietern oder ein gesamtes Datagrid-Steuerelement in Ihrer Spalte verschachteln, um eine Hierarchie von Informationen zu erstellen. Lassen Sie Ihrer Fantasie also freien Lauf.

Die fünf integrierten Spaltentypen sind ziemlich nützlich und erfüllen die Anforderungen der meisten Anzeigeszenarien, die Sie beim Arbeiten mit dem Datagrid-Steuerelement finden. Ohne Ihre eigene Kontrolle abzuleiten, bleiben Sie jedoch daran, alle ausgefallenen Dinge in einer TemplateColumn freiformlich zu platzieren. Durch das Erstellen benutzerdefinierter Spalten können Sie sich von diesen Einschränkungen befreien und Ihren Datagrid-Anwendungen umfangreiche Funktionen hinzufügen.

Zum Autor

Marcie "Datagrid Girl" Robillard, Microsoft MVP für ASP.NET, ist unabhängige Beraterin und Trainerin, die sich auf ASP.NET konzentriert. Ihre Spezialität ist die ASP.NET Datagrid, und sie hat ihr eine Website gewidmet, DatagridGirl.com. Auf der Website finden Sie Links zu den besten Datagrid-Artikeln, Büchern, die auf Datagrid-Inhalte überprüft wurden, und eine wachsende Sammlung von Häufig gestellten Fragen zu Datagrid. Marcie verschwendet auch, err, viel Zeit damit, die ASP.NET Foren zu moderieren und Antworten zu geben, wo Datagrid-Fragen gefunden werden. Die aktuellen Projekte von Marcie umfassen das Mentoring von Unternehmen bei der Entwicklung ihrer .NET-Fähigkeiten. Wenden Sie sich an , um spezielle Beratungen oder Schulungen in Ihrem organization zu erstellenMarcie@DatagridGirl.com.

Referenzen:

MetaBuilders.com. Kostenlose benutzerdefinierte Datagrid-Spalten, einschließlich Quellcode (C#).

DatagridGirl.com. Ressource für alles, was Datagrid ist.

ASP.NET Data Web Controls von Scott Mitchell, SAMS, 2003, ISBN-0672325012

© Microsoft Corporation. Alle Rechte vorbehalten.