TreeView erstellen mit MS IE Webcontrols
Autor: Jürgen Gutsch
Version: 1.0
Sprache: vb.net
Benötigt werden (mindestens):
.net Framework 1.0
MS IE Webcontrols
IIS 5.x
IE 5.5
Getestet auf:
WinXP
IIS 5.1
IE 6.0
Die MS IE Webcontrols
Die MS IE Webcontrols bestehen aus vier verschiedenen Controls, die sowohl clientseitig, als auch serverseitig in eine HTML-Seite eingebunden werden können.
Das sind "MenuBar", "TabStrip", "MultiPage" und das "TreeView".
Mehr zu diesen Webcontrols ist unter folgendem Link zu finden:
http://msdn.microsoft.com/[...]/webcontrols_entry.asp
Vorbereitung
Als erstes solltet Ihr ein beliebiges Verzeichnis anlegen. Legt anschließend innerhalb dieses Verzeichnisses ein weiteres mit dem Namen "bin" an.
Wenn die Webcontrols richtig installiert wurden, müsste im Windows Programmverzeichnis (c:\programme bzw. c:\program files) ein Verzeichnis mit dem Namen "Microsoft Internet Explorer WebControls" liegen. Dort liegt die Microsoft.Web.UI.WebControls.dll, die in das eben erstellte "bin"-Verzeichnis kopiert werden muss, damit wir diese später ohne Probleme ansprechen können.
Öffnet als nächstes den IIS-Manager und erstellt ein neues virtuelles Verzeichnis. Als Alias für das virtuelle Verzeichnis habe ich "TreeView" gewählt. Als Pfad gebt Ihr das zuerst erstellte Verzeichnis an.
Jetzt müsst Ihr Euch nur noch vergewissern, dass im Root des IIS (standartmäßig C:\Inetpub\wwwroot) das verzeichnis "aspnet_client" vorhanden ist. Dieses Verzeichnis enthält einige clientseitige Scripts, die für die Darstellung der Webcontrols benötigt werden.
Wenn das soweit erledigt ist, können wir uns daran machen, eine Testseite zu erstellen:
Das Htmlgerüst
Erstellt mit einem einem beliebigen Editor eine Datei mit der Endung "aspx" (ich habe den Namen "menu" gewählt).
<html>
<head>
<title>Test</title>
</head>
<body>
<form name="form1" id="form1" runat="server">
<table width="100%" border="0"
cellspacing="0" cellpadding="0">
<tr>
<td width="20%" id="cllMenu" runat="server"
valign="top"></td>
<td width="80%" valign="top"> </td>
</tr>
</table>
</form>
</body>
</html>
Das Gerüst steht: Wie jede aspx-Datei, hat auch diese einen <form>-Tag, dass, als Root-Control dient (mehr zur HtmlControll-Hierarchie folgt irgendwann in einem weiteren Artikel). Innerhalb des <form>-Tags sitzt eine Layouttabelle mit einem linken Menübereich, welcher 20% der Seitenbreiten einnimmt, in diese Tabellenzelle werden wir unser TreeView platziern. Aus diesem Grund habe ich der Zelle die ID "cllMenu" gegeben und das Attribut "runat=server" hinzugefügt (Ich habe also aus dieser einfachen Tabellenzelle ein serverseitiges HtmlControl vom Typ "System.Web.Ui.HtmlControls.HtmlTableCell" gemacht). Der rechte Bereich mit der Breite von 80% ist für Content reserviert (und für ein nächstes Tutorial mit dem namen "Abfangen von Events aus dem TreeView", o. ä.)
So, es fehlen noch ein paar Kleinigkeiten, bevor wir den HtmlCode ersteinmal eine weile ignorieren und uns die Datenbank und den VB-Code anschauen.
Am Seitenanfang müssen noch einige asp.net-spezifische @-Direktiven gesetzt werden, und außerden brauchen wir noch einen <script...></script> Bereich
Der Kopfbereich der Seite sollte jetzt wie folgt aussehen:
<%@ Page Language="VB" AutoEventWireup="false" Debug="true" %> <html> <head> <title>Test</title> <script language="VB" runat="server"> [...] </script> </head> <body> [...]
Die Datanbank
Folgende zwei Bilder sollten alles über die Menütabelle aussagen:


Der Programmcode
Der folgende Abschnit spielt sich nur zwischen dem <script>-Tag ab, so das ab jetzt kein Html mehr vorkommen wird. Einige von euch werden sich vieleicht wundern, dass Ich hier das übliche "<%@ Register ..." nicht verwende, um ein fremdes Control einzubinden, oder wieso im HtmlCode kein Tag "<prefix:TreeView ..." oder ähnlich vorkommt.
Aber der Grund hierfür ist einfach:
Seit ich asp.net kenne, habe ich eine abneigung gegen ASP-Tokens (<% ... %>) innerhalb von aspx-Seiten., genauso hab ich eine Abneigung gegen die Mischung aus Code und Design.
So erzeuge ich also keine WebControls mit "<prefix:ControlName ..." und mache euch keine Ausgabe mit <%=Variable%>. auf die Art habe ich die Möglichkeit, falls es irgendwann notwendig sein sollte, alles was sich zwischen den <script>-Tags befindet, problemlos in eine CodeBehind-Classe zu kopieren.
Wie üblich fange ich als erstes mit Sub "Page_Load" an und deklariere die ersten benötigten Variablen und Objekte:
' >>>>> DatenBank ConnectionString; Dim DS As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" _ & Server.MapPath("test.mdb") Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load If Not Page.IsPostBack then ' >>>>> Erzeugen des Treeviews: Dim tv As New Microsoft.Web.UI.WebControls.TreeView() ' >>>>> Das TreeView in die Zelle "cllMenu" einfügen: cllMenu.Controls.Add(tv) End If End Sub
Oben sieht man schon meine Art, ein WebControls zu erzeugen und an eine bestimmte Stelle im HtmlCode einzufügen
Noch wird man nicht viel vom TreeView sehen, wenn man die Seite aufrufen würde. Was wir jetzt noch brauchen, sind die Daten aus der DatenBank. Diese Lese ich in ein DataSet ein, was mir eine einfache Handhabung der Daten Ermöglicht, zudem Brauche ich die Verbindung zur DB nur einmal kurz zu öffnen, und kann sie dann getrost vergessen (nachdem ich sie wieder geschlossen habe, natürlich).
Folgender Code zeigt die Funktion, die mir die Daten aus der DB ließt und anschließend ein DataSet zurückliefert:
Function getDataSet() As System.Data.DataSet ' >>>>> Verbindung zur DB erstellen Dim Connection As New System.Data.OleDb.OleDbConnection(DS) ' >>>>> Verbindung öffnen Connection.Open() ' >>>>> SqlQuery Dim strSQL As String = "SELECT * FROM menu" ' >>>>> OleDbCommand erzeugen Dim Command As _ New System.Data.OleDb.OleDbCommand(strSQL, Connection) ' >>>>> DataAdapter erzeugen Dim DataAdapter As New System.Data.OleDb.OleDbDataAdapter(Command) ' >>>>> Das zu Füllende DataSet erzeugen Dim DataSet As New System.Data.DataSet() ' >>>>> DataSet mit Hilfe des Adapters Füllen. ' >>>>> Das erzeugte DataTable erhält hier noch den Namen "MENU" DataAdapter.Fill(DataSet,"MENU") ' >>>>> Adapter zertören DataAdapter.Dispose() ' >>>>> Command zertören Command.Dispose() ' >>>>> Verbindung schließen Connection.Close() ' >>>>> Verbindung zertören Connection.Dispose() ' >>>>> und zuletzt das DataSet zurückgeben: Return DataSet End Function
Als nächstes habe ich eine Sub geschrieben, die das DataSet rekursiv durchgeht und so jeden Menüpunkt (TreeNode) erzeugt. Dabei muss man sich deutlich machen, dass ein TreView-Control aus mehreren TreeNode-Controls besteht, die wiederum weitere TreeNodes enthalten können.
Function getMeTreeView( _ ByRef TreeNode As Microsoft.Web.UI.WebControls.TreeNode, _ ByRef DataSet As System.Data.DataSet, _ ByVal parentID As Integer) _ As Microsoft.Web.UI.WebControls.TreeNode Dim tn As Microsoft.Web.UI.WebControls.TreeNode ' >>>>> Folgendes Statement füllt ein DataRow-Array mit ' >>>>> allen Daten aus dem DataSet, bei denen die "m_parent" ' >>>>> der als Parameter übergebene ParentID entspricht Dim dr() As System.Data.DataRow = _ DataSet.Tables("MENU").Select("m_parent=" & parentID) ' >>>>> Variablen für die TreeNodes: Dim strText As String Dim strLink As String Dim intId As Integer ' >>>>> Zähler für die For-Schleife: Dim i As Integer ' >>>>> Diese Schleife geht alle Daten im DataRow-Array durch: For i = 0 to dr.Length -1 ' >>>>> TreeNode-Text: strText = dr(i).Item("m_text").ToString ' >>>>> TreeNode Link: strLink = dr(i).Item("m_link").ToString ' >>>>> ID des TreeNodes: intId = dr(i).Item("m_id") ' >>>>> neues TreeNode erzeugen: tn = New Microsoft.Web.UI.WebControls.TreeNode ' >>>>> id Setzen: tn.ID = intId ' >>>>> Text setzen: tn.Text = strText ' >>>>> Schriftart und -Größe Setzen: tn.DefaultStyle.Add("font-family", "arial") tn.DefaultStyle.Add("font-size", "11px") ' >>>>> Link setzen, wenn vorhanden: If strLink <> "-" Then tn.NavigateUrl = strLink ' >>>>> rekursiver Aufruf dieser Sub, wobei die Aktuelle ' >>>>> ID als neue parendID übergeben wird: getMeTreeView(tn, DataSet, intId) ' >>>>> als letztes wird das eben erzeugte TreeNode dem ' >>>>> dem übergebenen hinzugefügt: TreeNode.Nodes.Add(tn) Next End Function
Jetzt bleibt uns nur noch eines zu tun, nämlich die beiden eben gezeigten Funktionen in der Page_Load aufzurufen:
Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load If Not Page.IsPostBack then ' >>>>> Erzeugen des TreeViews: Dim tv As New Microsoft.Web.UI.WebControls.TreeView() ' >>>>> Eigenschaften des TreeViews setzen: tv.ShowLines = True tv.ShowPlus = True tv.ShowToolTip = True ' >>>>> neues TreeNode erzeugen: Dim tn As New Microsoft.Web.UI.WebControls.TreeNode ' >>>>> ID Setzen: tn.ID = 0 ' >>>>> Text setzen tn.Text = "ROOT" ' >>>>> Scriftformat tn.DefaultStyle.Add("font-family", "arial") tn.DefaultStyle.Add("font-size", "11px") ' >>>>> Rekursion aufrufen und Untergeordnete Nodes erzeugen: getMeTreeView(tn, getDataSet(),0) ' >>>>> TreeNode mit untergeordneten Nodes ' >>>>> dem TreeView hinzufügen tv.Nodes.Add(tn) ' >>>>> Das TreeView in die Zelle "cllMenu" einfügen: cllMenu.Controls.Add(tv) End If End Sub
Das war es auch schon. Diese paar Zeilen sind nur nötig, um ein funktionierendes Baummenü zu schreiben
Ein Aufruf der Seite sollte jetzt folgende Bilder erzeugen:

Zu guter letzt gibt es das Beispiel wie immer zum saugen und testen:
Donwload: treeview01.zip (68 KB)