Die Community zu .NET und Classic VB.
Menü

VB.NET-Tipp 0079: Mehrspaltige Darstellung von Listbox und Combobox-Einträgen

 von 

Beschreibung

Dieser Tipp demonstriert das bei .NET-Controls weit verbreitete Ownerdrawing, bei dem die Einträge frei gezeichnet werden können. Combobox und Listbox können hier vollkommen identisch behandelt werden. Für das beim Zeichnen verwendete StringFormat sind Tabulatoren eingestellt, so, dass ein Tab im Item-Text als Spalten-Trenner interpretiert wird.

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 [11,93 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.Deployment
'  - System.Drawing
'  - System.Windows.Forms
'  - System.Xml
'
' Imports: 
'  - Microsoft.VisualBasic.ControlChars
'  - System
'  - System.Windows.Forms
'

' ##############################################################################
' ############################# frmColumnCombo.vb ##############################
' ##############################################################################
Imports Microsoft.VisualBasic.ControlChars
Imports System.Drawing

' ###### Wichtige Einstellungen im Form-Designer: #######
' List-/Combo-Box.DrawMode = DrawMode.OwnerDrawFixed 
' Bei der Combo stellt die Textbox-Funktionalität Tabulatoren falsch dar, also:
'  ComboBox.DropDownStyle = DropDownList 

Public Class frmColumnCombo
    ' In diesem StringFormat-Objekt werden die 
    ' Tabulator-Einstellungen gespeichert
    Private _SF As New StringFormat

    ' Dieser Brush wird in _DrawItem() immer wiederverwendet
    Private _DrawStringBrush As New SolidBrush(Color.Black)

    ' Die Spalten innerhalb der Einträge sind durch Tabulatoren getrennt
    Private _DataSource As String() = { _
       String.Format("Entry00{0}Entry01{0}Entry02", Tab), _
       String.Format("Entry10{0}Entry11{0}Entry12", Tab), _
       String.Format("Entry20{0}Entry21{0}Entry22", Tab), _
       String.Format("Entry30{0}Entry31{0}Entry32", Tab), _
       String.Format("Entry40{0}Entry41{0}Entry42", Tab), _
       String.Format("Entry50{0}Entry51{0}Entry52", Tab)}

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

        _SF.SetTabStops(0, New Single() {0, 15, 40})

        ' Dieselbe DataSource an Listbox und Combo zuweisen
        For Each Ctl As ListControl In _
            New ListControl() {Me.ListBox1, Me.ComboBox1}

            Ctl.DataSource = _DataSource
        Next
    End Sub

    ' Dieser Handler abonniert das _DrawItem-Event sowohl der 
    ' Combo als auch der Listbox
    Private Sub ListControl_DrawItem( _
        ByVal sender As Object, _
        ByVal e As DrawItemEventArgs) _
        Handles ListBox1.DrawItem, ComboBox1.DrawItem

        If e.Index < 0 Then Return

        ' DrawItemEventArgs enthalten nicht nur Daten, sondern 
        ' auch 2(!) Zeichenfunktionen
        e.DrawBackground()

        ' beim Zeichnen selektierter Item ist e.ForeColor invertiert
        _DrawStringBrush.Color = e.ForeColor

        ' Direkter Zugriff auf die DataSource spart ein 
        ' Umwandeln der ListControl-Items
        Dim S As String = _DataSource(e.Index)

        ' Beachte, dass diese DrawString-Überladung das 
        ' StringFormat-Objekt verwendet
        e.Graphics.DrawString(S, e.Font, _DrawStringBrush, e.Bounds, _SF)
        If CBool(e.State And DrawItemState.Focus) Then
            e.DrawFocusRectangle()
        End If
    End Sub

    Private Sub frmColumnCombo_Disposed(ByVal sender As Object, _
            ByVal e As EventArgs) Handles Me.Disposed

        ' Für alle Objekte, die IDisposable implementieren, sollte man 
        ' .Dispose() aufrufen, wenn sie nicht mehr gebraucht werden. 
        ' Andernfalls kann vorkommen, daß Systemressourcen nicht 
        ' mehr freigegeben werden.
        For Each D As IDisposable In New IDisposable() {_SF, _DrawStringBrush}
            D.Dispose()
        Next
    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.