12.11 Das DataList-Steuerelement
 
Das DataList-Steuerelement ist dem Repeater-Steuerelement sehr ähnlich. Die Ähnlichkeit geht so weit, dass Sie beispielsweise in db_21.aspx den Namen Repeater einfach gegen DataList austauschen können. Anschließend erhalten Sie exakt das gleiche Ergebnis wie bei der Verwendung des Repeater-Steuerelements.
Das DataList bietet folgende zusätzliche Merkmale:
|
Ähnlich wie das DataGrid-Steuerelement ermöglicht auch das DataList-Element das In-Place-Editing. Dafür steht die Vorlage EditItemTemplate zur Verfügung. |
|
Einträge können selektiert werden. Die Vorlage SelectedItemTemplate definiert das Aussehen eines selektierten Eintrags. |
|
Für die einzelnen Templates können Stileigenschaften definiert werden. Dazu dienen die Eigenschaften AlternatingItemStyle, EditItemStyle, FooterStyle, HeaderStyle, ItemStyle, SelectedItemStyle und SeparatorStyle. |
|
Mit ShowFooter und ShowHeader können Sie den Kopf- und den Fußbereich gezielt ein- und ausblenden. |
|
Mit der Eigenschaft RepeatColumns legen Sie die Anzahl der Spalten fest, in denen die Einträge dargestellt werden sollen. RepeatDirection definiert, ob diese Spalten von links nach rechts oder von oben nach unten aufgefüllt werden. RepeatLayout legt fest, ob die Darstellung mit Hilfe einer Tabelle erfolgt oder fließend umbricht. |
12.11.1 In-Place-Editing mit dem DataList-Steuerelement
 
db_23.aspx realisiert die Möglichkeit des In-Place-Editings.
<!-- db_23.aspx -->
<%@ Page Language="VB" Debug="True" Strict="True"
EnableViewstate="true" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.OleDb" %>
<script runat="server">
Dim connStr As String="Provider=Microsoft.Jet." _
& "OLEDB.4.0;Data Source=" _
& "C:\ASPdotNETBuch\Listings\Nordwind.mdb;"
Sub Page_Load (ByVal Sender As Object, _
ByVal E As EventArgs)
If not IsPostBack Then
Datenlesen()
End If
End Sub
Sub Datenlesen()
Dim conn As New OleDbConnection(connStr)
conn.Open()
Dim sql As String
sql = "SELECT * FROM Versandfirmen"
Dim cmd As New OleDbCommand(sql, conn)
Dim myDataReader As OleDbDataReader
myDataReader = cmd.ExecuteReader()
myDataList.DataSource = myDataReader
myDataList.DataBind()
myDataReader.Close()
conn.Close()
End Sub
Function executeSQL (ByVal inSQL As String) As Integer
Dim conn As New OleDbConnection(connStr)
conn.Open()
Dim cmd As New OleDbCommand(inSQL, conn)
Return cmd.ExecuteNonQuery()
conn.Close()
End Function
Public Sub OnUpdate(ByVal source As Object, _
ByVal e As DataListCommandEventArgs)
Dim telNeu, firmenID, sql As String
telNeu = _
CType(e.Item.FindControl("txtTel"), TextBox).Text
firmenID = _
CStr(myDataList.DataKeys(e.Item.ItemIndex))
sql ="Update Versandfirmen SET Telefon='" _
& telNeu _
& "' WHERE [Firmen-Nr] = " & firmenID
' Testweise das SQL-Statement ausgeben
ausgabe.innerHTML = sql
executeSQL(sql)
myDataList.EditItemIndex = -1
System.Threading.Thread.Sleep (500)
Datenlesen()
End Sub
Public Sub OnDelete(ByVal source As Object, _
ByVal e As DataListCommandEventArgs)
Dim firmenID, sql As String
firmenID = _
CStr(myDataList.DataKeys(e.Item.ItemIndex))
sql = "DELETE From Versandfirmen " _
& "WHERE [Firmen-Nr]=" _
& firmenID
' Testweise das SQL-Statement ausgeben
ausgabe.innerHTML = sql
executeSQL(sql)
myDataList.EditItemIndex = -1
System.Threading.Thread.Sleep (500)
Datenlesen()
End Sub
Public Sub OnEdit(ByVal source As Object, _
ByVal e As DataListCommandEventArgs)
myDataList.EditItemIndex = e.Item.ItemIndex
Datenlesen()
End Sub
Public Sub OnCancel(ByVal source As Object, _
ByVal e As DataListCommandEventArgs)
myDataList.EditItemIndex = -1
Datenlesen()
End Sub
</script>
<html><head><title>DataList-Steuerelement</title>
</head><body>
<h3>DataList-Steuerelement</h3>
<form runat="server">
<asp:DataList id="myDataList" runat="server"
HeaderStyle-Font-Bold
DataKeyField="Firmen-Nr"
OnEditCommand="OnEdit"
OnDeleteCommand="OnDelete"
OnCancelCommand="OnCancel"
OnUpdateCommand="OnUpdate" >
<HeaderTemplate>
Versandfirmen mit Tel-Nr.:
</HeaderTemplate>
<ItemTemplate>
<%# DataBinder.Eval _
(Container.DataItem, "Firma") %>
<td><%# DataBinder.Eval _
(Container.DataItem, "Telefon")%>
<td><asp:Button CommandName="Edit"
runat="server"
Text ="Tel.-Nr. ändern" />
</ItemTemplate>
<EditItemTemplate>
<%# DataBinder.Eval _
(Container.DataItem, "Firma") %>
<td><asp:TextBox runat="server" id="txtTel"
Text='<%# DataBinder.Eval _
(Container.DataItem, "Telefon") %>'
/>
<td>
<asp:Button CommandName="Update"
Text="Speichern"
runat="server"
id="btnUpdate" />
<asp:Button CommandName="Cancel"
Text="Abbrechen"
runat="server"
id="btnCancel" />
<asp:Button CommandName="Delete"
Text="Datensatz löschen"
runat="server"
id="btnDelete" />
</EditItemTemplate>
</asp:DataList>
<p id="ausgabe" runat="server" />
</form></body></html>
Abbildung 12.22 zeigt die unterschiedlichen Darstellungen im Browser. Im HTML-Abschnitt von db_23.aspx deklariert das DataList-Element drei Templates, und zwar das HeaderTemplate, das ItemTemplate und das EditItemTemplate.
HeaderTemplate
Die Eigenschaft RepeatLayout wird nicht eigens festgelegt, so dass automatisch die Tabellenform gewählt wird. Der HeaderTemplate definiert beispielsweise lediglich den Text Versandfirmen mit Tel-Nr.:. Wenn man im Browser einen Blick auf den generierten Quellcode wirft, erkennt man, dass ASP.NET folgenden Code generiert hat:
<table id="myDataList" cellspacing="0" border="0" style="border-collapse:collapse;">
<tr><td style="font-weight:bold;">
Versandfirmen mit Tel-Nr.:
</td></tr>
 Hier klicken, um das Bild zu Vergrößern
Abbildung 12.22 Auch das DataList-Steuerelement ermöglicht das In-Place-Editing.
Offenkundig kümmert sich das Steuerelement selbst um die benötigten Tabellenelemente, so dass es nicht nötig ist, Tags wie <tr> und <td> selbst zu setzen.
Das Tag für die Kopfzeile enthält die Stileigenschaft <td style="font-weight:bold;">. Hier findet sich das Attribut HeaderStyle-Font-Bold wieder, das innerhalb des DataList-Elements gesetzt wurde.
ItemTemplate
In der Deklaration von ItemTemplate fällt auf, dass hier nun doch das <td>-Tag verwendet wird. Davon ausgenommen ist die erste Spalte für die Firma, die kein <td>-Tag erhält. Für die erste Spalte generiert das DataList-Element automatisch das benötigte td-Element.
Die hier gewählte Verwendung ist gewissermaßen untypisch. Das DataList-Element ist so gedacht, dass die Einträge alle innerhalb einer Zelle erscheinen sollen. Die Ausweitung auf mehrere Spalten ist eher die Domäne des DataGrid-Steuerelements.
Für die dritte Spalte fügt das ItemTemplate eine Edit-Schaltfläche hinzu. Mit Hilfe dieser Schaltfläche kann der Anwender die Telefon-Nummer ändern. Die Zuordnung zu einer Prozedur erfolgt im DataList-Element selbst mit dem Attribut OnEditCommand="OnEdit". Der Skriptteil von db_23.aspx enthält die Prozedur OnEdit().
EditItemTemplate
Auch EditItemTemplate definiert die Inhalte für drei Spalten. Die erste Spalte ist identisch mit dem Inhalt bei ItemTemplate. Hier wird lediglich der Inhalt der Spalte Firma ausgegeben.
Die zweite Spalte erhält ein TextBox-Element. Hier kann der Anwender die Telefonnummer bearbeiten. Über das Text-Attribut wird die aktuelle Nummer in das Textfeld geschrieben. Außerdem erhält das Textfeld die id="txtTel". Dieses id-Attribut wird später die OnUpdate-Prozedur wieder aufgreifen.
Die dritte Spalte erhält drei Schaltflächen. Sie ermöglichen das Speichern der Änderungen, das Abbrechen des Vorgangs und den Vorgang Datensatz löschen. Die Schaltfläche auf der Hauptseite heißt Tel-Nr. ändern. Daher ist es nicht in sich stimmig, dass hier auch die Möglichkeit zum Löschen des Datensatzes geboten wird. Diese Option habe ich hier lediglich ergänzt, um das Prinzip zu demonstrieren.
Die drei Button-Elemente definieren jeweils das CommandName-Attribut. Im DataList-Element erfolgt die Zuordnung zu einer konkreten Prozedur, z. B. OnUpdateCommand="OnUpdate".
Im DataList-Element wird außerdem der Wert DataKeyField="Firmen-Nr" gesetzt. Das DataKeyField-Attribut legt das Schlüsselfeld fest, über das auf die zugrunde liegende Tabelle zugegriffen werden kann.
Page_Load()
Beim ersten Öffnen der Seite soll die Prozedur Datenlesen() ausgeführt werden, sonst passiert nichts.
Datenlesen()
Die Prozedur Datenlesen() liest die Daten in das DataList-Steuerelement ein und führt die Datenbindung aus. Datenlesen() wird von Page_Load() aufgerufen und von den vier Prozeduren, die die Daten bearbeiten. Der Wert von e.Item.EditItemIndex steuert jeweils, welcher Datensatz bearbeitet werden soll. Wenn dieser Wert auf -1 steht, wird kein Datensatz bearbeitet.
executeSQL()
executeSQL() führt einen SQL-Befehl aus, der keine Query enthält, sondern einen UPDATE- oder einen DELETE-Befehl. Die Prozeduren OnUpdate() und OnDelete() greifen auf diese Hilfsprozedur zurück.
OnUpdate()
OnUpdate()baut den SQL-Befehl für die Datenbankaktualisierung zusammen. Der SQL-Befehl wird für Debugging-Zwecke unter dem DataList-Steuerelement ausgegeben und mit Hilfe von executeSQL() ausgeführt.
Dieser SQL-Befehl hat beispielsweise diese Form:
Update Versandfirmen SET Telefon='8876753' WHERE [Firmen-Nr] = 8
Der SQL-Befehl enthält zwei variable Bestandteile: die Telefonnummer, die der Anwender eingegeben hat, und die Firmen-Nr, die für diese Tabelle das Schlüsselfeld darstellt.
Die Eingabe des Anwenders ermitteln Sie mit dem Ausdruck e.Item.FindControl("txtTel"), der das Steuerelement mit der id txtTel ausfindig macht. Anschließend kann dieses Objekt in ein Objekt vom Typ TextBox konvertiert und die Text-Eigenschaft ausgelesen werden.
Die Firmen-Nr des Datensatzes, der bearbeitet wird, erreichen Sie über die DataKeys-Eigenschaft des DataList-Steuerelements. Mit myDataList.DataKeys(e.Item.ItemIndex) ermitteln Sie den gesuchten Wert. Ermöglicht wird dieses Verfahren durch das Attribut DataKeyField="Firmen-Nr" des DataList-Elements.
Damit haben Sie alle benötigten Bestandteile für den SQL-Befehl ermittelt. Der Befehl wird mit Hilfe der Prozedur executeSQL() ausgeführt. Anschließend wird die EditItemIndex-Eigenschaft des DataList-Objekts auf -1 gesetzt und die Daten werden erneut mit Datenlesen() ermittelt. Damit wird die Tabelle neu aufgebaut.
| Achtung Bleibt noch der Aufruf System.Threading.Thread.Sleep (500) zu erklären. Wenn Sie diesen Befehl auskommentieren und die Prozedur ausführen, können Sie eine merkwürdige Beobachtung machen. Die Änderung wird in der Datenbank zwar korrekt ausgeführt. Die Änderung wird aber nach dem Anklicken von Speichern nicht im Browser angezeigt. Erst bei einem Reload werden die Daten korrekt ausgelesen.
|
Der Grund dafür ist darin zu suchen, dass ASP.NET die Daten ausliest, noch bevor die Änderungen in der Datenbank gespeichert werden konnten. Daraus resultiert die Idee, vor dem Aufruf der Prozedur Datenlesen() eine künstliche Pause von 500 Millisekunden einzulegen. Diese Zeit reicht aus, damit die Änderungen in der Access-Datenbank auch wirklich ankommen. Die Daten werden mit dieser kleinen Pause korrekt angezeigt.
OnDelete()
OnDelete() arbeitet ähnlich wie OnUpdate(). Der SQL-Befehl wird zusammengesetzt und mit executeSQL() ausgeführt. Anschließend wird ebenfalls eine künstliche Pause eingelegt und die Tabelle wird neu aufgebaut.
OnEdit()
OnEdit() wird aufgerufen, wenn der Anwender die Schaltfläche Tel.-Nr. ändern anklickt. Die Methode setzt die EditItemIndex-Eigenschaft auf den Wert des Datensatzes, den der Anwender angeklickt hat, und veranlasst anschließend mit Datenlesen() den erneuten Aufbau der Tabelle.
OnCancel()
Die Funktionsweise von OnCancel() entspricht der Arbeitsweise von OnEdit(). Die EditItemIndex-Eigenschaft wird auf -1 gesetzt. Das bedeutet, dass keine Zeile bearbeitet werden soll. Mit dieser Einstellung wird der erneute Aufbau der Tabelle veranlasst.
|