Die Community zu .NET und Classic VB.
Menü

VB.NET-Tipp 0088: Combobox-Features - Befüllung, Darstellung, Databinding

 von 

Beschreibung

Häufig nicht bekannt ist die Tatsache, dass Comboboxen nicht nur Strings enthalten können, sondern problemlos jede Art von Objekt. Liegen die Einträge in geeigneten Auflistungen vor (IList / IList(Of T)), kann man anstelle einer Befüllungs-Schleife einfach die Auflistung selbst als DataSource zuweisen. Der Anzeige-Text der Einträge kann mit Festlegung eines DisplayMembers und/oder eines Formatstrings nachhaltig beeinflusst werden. Verwendung von DataBinding kann die Verarbeitung des SelectedIndexChanged-Ereignisses erübrigen und stellt die für aufwändige Oberflächen günstigere Trennung von Ansicht und Daten her.

Dieser Tipp demonstriert die oben beschriebene Datenbindung und zeigt, auf welche Weise Daten zu einem Combobox-Steuerelement hinzugefügt werden können.

Anmerkung: Die gezeigten Features sind gleichfalls auf Listboxen anwendbar.

Schwierigkeitsgrad:

Schwierigkeitsgrad 1

Framework-Version(en):

.NET Framework 1.0, .NET Framework 1.1, .NET Framework 2.0, .NET Framework 3.0, .NET Framework 3.5

.NET-Version(en):

Visual Basic 2002, Visual Basic 2003, Visual Basic 2005, Visual Basic 2008

Download:

Download des Beispielprojektes [15,07 KB]

' Dieser Quellcode stammt von http://www.activevb.de
' und kann frei verwendet werden. Für eventuelle Schäden
' wird nicht gehaftet.

' Um Fehler oder Fragen zu klären, nutzen Sie bitte unser Forum.
' Ansonsten viel Spaß und Erfolg mit diesem Source!

' Projektversion:   Visual Studio 2005
' Option Strict:    An
'
' Referenzen: 
'  - System
'  - System.Data
'  - System.Drawing
'  - System.Windows.Forms
'  - System.Xml
'
' Imports: 
'  - Microsoft.VisualBasic
'  - Microsoft.VisualBasic.ControlChars
'  - System
'  - System.Collections
'  - System.Collections.Generic
'  - System.Data
'  - System.Diagnostics
'  - System.Drawing
'  - System.Drawing.Drawing2D
'  - System.Windows.Forms
'

' ##############################################################################
' ################################# Canvas.vb ##################################
' ##############################################################################
Imports System.ComponentModel

''' <summary>einfaches Control zur Anzeige eines GraphicsPathes</summary>
Public Class Canvas : Inherits Control

    Private _TemplatePath As GraphicsPath
    Private _DrawPath As New GraphicsPath
    Private _Matrix As New Matrix

    ''' <summary>
    ''' Canvas zeigt eine auf seine Größe skalierte Kopie dieses 
    ''' GraphicsPathes an
    ''' </summary>
    <Bindable(True)> _
    Public Property TemplatePath() As GraphicsPath
        ' Das Bindable(True)-Attribut ermöglicht, Databinding auch im 
        ' Form-Designer einzustellen
        Get
            Return _TemplatePath
        End Get
        Set(ByVal NewValue As GraphicsPath)
            If _TemplatePath Is NewValue Then Return
            _TemplatePath = NewValue
            ApplyChanges()
        End Set
    End Property

    Protected Overrides Sub OnSizeChanged(ByVal e As System.EventArgs)
        MyBase.OnSizeChanged(e)
        ApplyChanges()
    End Sub

    Protected Overrides Sub OnPaint( _
        ByVal e As System.Windows.Forms.PaintEventArgs)

        MyBase.OnPaint(e)
        If _TemplatePath Is Nothing Then Return
        e.Graphics.DrawPath(Pens.Red, _DrawPath)
    End Sub

    Private Sub ApplyChanges()
        ' Lege in _DrawPath eine auf meine Größe skalierte Kopie von 
        ' _TemplatePath(an)
        If _TemplatePath Is Nothing Then Return
        _Matrix.Reset()
        Dim Bounds As RectangleF = _TemplatePath.GetBounds
        Dim Sz As SizeF = MyBase.ClientSize - New Size(1, 1)
        With _TemplatePath.GetBounds
            ' ObenLinks auf Nullpunkt schieben
            _Matrix.Translate(-.X, -.Y, MatrixOrder.Append)

            ' Skalieren
            _Matrix.Scale(Sz.Width / .Width, _
                Sz.Height / .Height, MatrixOrder.Append)
        End With
        _DrawPath.Reset()
        _DrawPath.AddPath(_TemplatePath, False)
        _DrawPath.Transform(_Matrix)
        MyBase.Invalidate()
    End Sub

    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing AndAlso _DrawPath IsNot Nothing Then
            _DrawPath.Dispose()
            _Matrix.Dispose()
            _DrawPath = Nothing
        End If
        MyBase.Dispose(disposing)
    End Sub
End Class

' ##############################################################################
' ############################ frmComboFeatures.vb #############################
' ##############################################################################
Public Class frmComboFeatures
    Private Pts As PointF() = New PointF() { _
        New PointF(-4, 0), New PointF(-3, -3), New PointF(0, -4), _
        New PointF(3, -3), New PointF(4, 0), New PointF(3, 3), _
        New PointF(0, 4), New PointF(-3, 3)}

    Private Sub Form_Load(ByVal sender As Object, _
        ByVal e As EventArgs) Handles Me.Load

        SetupTab1()
        SetupTab2()
    End Sub

    Private Sub SetupTab1()
        ' Die bekannteste Art eine Combo zu befüllen ist wohl jeden 
        ' anzuzeigenden String einzeln hinzuzufügen
        For Each Pt As PointF In Pts
            ComboBox1.Items.Add(Pt.ToString)
        Next
        ComboBox1.SelectedIndex = 0

        ' Man kann aber einfacher die Objekte selbst hinzufügen
        ' Zusätzlicher Vorteil: Über die Items-Property können nun nicht nur 
        ' String-Repräsantionen der Objekte abgerufen werden, sondern die 
        ' Objekte selbst.
        ' In diesem Fall bedient sich die Combobox zur Ermittlung der Anzeige 
        ' automatisch der .ToString()-Funktion der Objekte.
        For Each Pt As PointF In Pts
            ComboBox2.Items.Add(Pt)
        Next
        ComboBox2.SelectedIndex = 0

        ' Über die "DisplayMember"-Eigenschaft der Combo kann bestimmt werden,
        ' daß nicht Item.ToString() dargestellt wird, sondern die spezifizierte 
        ' Eigenschaft. Hier wird Pointf.X angezeigt 
        ' (Pointf.Y dadurch ausgeblendet)
        ComboBox3.DisplayMember = "X"
        For Each Pt As PointF In Pts
            ComboBox3.Items.Add(Pt)
        Next
        ComboBox3.SelectedIndex = 0

        ' Liegen die Daten bereits in einer Auflistung vor (hier: Array), so 
        ' kann man diese gegebenenfalls direkt als DataSource angeben. Diese 
        ' Variante ist der erste Schritt zum Databinding.
        ' Vorraussetzung: Die Auflistung muß die IList- oder IList(Of T)-
        ' Schnittstelle implementieren (derlei Informationen erfährt man im 
        ' ObjectBrowser). Zusätzlich kann die Darstellung durch Angabe eines 
        ' FormatStrings beeinflußt werden
        ComboBox4.DisplayMember = "Y"
        ' Zeige Zahlenwerte als Währung an
        ComboBox4.FormatString = "c"
        ComboBox4.DataSource = Pts
    End Sub

    Private Sub SetupTab2()
        ' Hier will ich verschiedene GraphicsPathes mit Namen verknüpfen. Die 
        ' Namen sollen in der Combo angezeigt werden, die Pathes im 
        ' Canvas-Control. Statt einer eigens implementierten Daten-Klasse 
        ' nehme ich mir als Name-Path-Container einfach 
        ' KeyValuePair(Of T1, T2) her 
        Dim Entries As New List(Of KeyValuePair(Of String, GraphicsPath))
        Dim GP As New GraphicsPath
        GP.AddEllipse(0, 0, 4, 4)
        Entries.Add(New KeyValuePair(Of String, GraphicsPath)("Ellipse", GP))

        GP = New GraphicsPath
        GP.AddRectangle(New Rectangle(0, 0, 4, 4))
        Entries.Add(New KeyValuePair(Of String, GraphicsPath)("Rectangle", GP))

        GP = New GraphicsPath
        GP.AddLine(0, 0, 4, 4)
        Entries.Add(New KeyValuePair(Of String, GraphicsPath)("Line", GP))

        GP = New GraphicsPath
        GP.AddLines(Pts)
        Entries.Add(New KeyValuePair(Of String, GraphicsPath)("Lines", GP))

        GP = New GraphicsPath
        GP.AddPolygon(Pts)
        Entries.Add(New KeyValuePair(Of String, GraphicsPath)("Polygon", GP))

        GP = New GraphicsPath
        GP.AddBeziers(New PointF() {Pts(0), Pts(1), Pts(7), Pts(2), Pts(5), _
            Pts(3), Pts(4)})
        Entries.Add(New KeyValuePair(Of String, GraphicsPath)("Beziers", GP))

        ' ComboBox5 wird per .DataSource-Property die Steuerung des 
        ' DataBindings übertragen, an welches Canvas1 ebenfalls angeschlossen 
        ' wird. Auf diese Weise kann ohne weiteren Code mit der Combo gewählt 
        ' werden, was Canvas1 anzeigt.
        ComboBox5.DisplayMember = "Key"
        ComboBox5.DataSource = Entries
        Canvas1.DataBindings.Add("TemplatePath", Entries, "Value")
    End Sub
End Class

Ihre Meinung  

Falls Sie Fragen zu diesem Artikel haben oder Ihre Erfahrung mit anderen Nutzern austauschen möchten, dann teilen Sie uns diese bitte in einem der unten vorhandenen Themen oder über einen neuen Beitrag mit. Hierzu können sie einfach einen Beitrag in einem zum Thema passenden Forum anlegen, welcher automatisch mit dieser Seite verknüpft wird.