[vb.net] CheckedListbox

Gepostet am: Sep 09, 2011 11:47:8 AM

VB.net stellt das Steuerelement (Control) CheckedListbox zur Verfügung. Ich muss ehrlich gestehen, dass ich es bisher noch nie wirklich gebraucht habe, aber in diesem Fall hat es sich angeboten. 

Grundsätzlich kann man das selbe mit einem ListView erzeugen, wenn man 

> Me.myListView.CheckBoxes = True

setzt. Jedoch hinsichtlich der Anwendung der beiden Steuerelemente gibt es gigantische Unterschiede. 

Hinzufügen von Elementen

Prinzipiell funktioniert das Hinzufügen wie gewöhnlich

> Me.CheckedListBox.Items.Add(strLine)

Um beispielsweise eine Datei auszulesen und in eine CheckedListbox zu schreiben funktioniert folgender Code:

TextDatei2CheckedListBox

Private Sub TextDatei2CheckedListBox(ByVal smyFile As String)         Dim objStreamReader As StreamReader = File.OpenText(smyFile)         Dim strLine As String = String.Empty          Do             strLine = objStreamReader.ReadLine()             If Len(Trim(strLine)) > 0 Then                 Me.CheckedListBox.Items.Add(strLine)             End If         Loop Until strLine Is Nothing          objStreamReader.Close()End Sub

Um ein einzelnes Element, beispielsweise von einer Textbox anzufügen würde folgendes funktionieren

neuesElementhinzufügen_Click

Private Sub neuesElementhinzufügen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _         Handles neuesElementhinzufügen.Click         Me.CheckedListBox.Items.Add(Me.neuesElement.Text)End Sub

Weiters funktioniert auch AddRange usw.

alle Elemente markieren

Nachdem man alle gewünschten Elemente nun in einer CheckedListbox hat, möchte man beispielsweise alle Elemente markieren. 

alleElementemarkieren

Private Sub alleElementemarkieren_M1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _         Handles alleElementemarkieren_M1.Click         For i As Integer = 0 To Me.CheckedListBox.Items.Count - 1             Me.CheckedListBox.SetItemChecked(i, True)         Next i End SubPrivate Sub alleElementemarkieren_M2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _         Handles alleElementemarkieren_M2.Click         For i As Integer = 0 To Me.CheckedListBox.Items.Count - 1             Me.CheckedListBox.SetItemCheckState(i, CheckState.Checked)         NextEnd Sub

Die Methode 1 stellt auch die gängigste Vorgehensweise generell in Bezug auf eine CheckListBox dar. Das durchlaufen aller Elemente anhand ihres Index.

Auswahl invertieren

Ein weiteres öfters mal benötigtes Snipplet ist die Invertierung der Auswahl. maW. Man möchte, dass die angehackten Checkboxen als nicht angehackt aufscheinen und umgekehrt. Auch das geht recht einfach.

alleElementeinvertieren_M1

Private Sub alleElementeinvertieren_M1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _         Handles alleElementeinvertieren_M1.Click         For i As Integer = 0 To Me.CheckedListBox.Items.Count - 1             Me.CheckedListBox.SetItemChecked(i, Not (Me.CheckedListBox.GetItemChecked(i)))         Next i End Sub

ausgewählte (angehackte) Elemente ausgeben

Nachdem man nun bestimmte Elemente ausgewählt hat indem man sie angehackt hat, stellt sich die Frage, wie man zu den Werten der ausgewählten Einträge kommt. Hierzu gibt es mehrere Möglichkeiten

ausgewählteElementeausgeben

Private Sub ausgewählteElementeausgeben_M1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _         Handles ausgewählteElementeausgeben_M1.Click         For Each myitem As Object In CheckedListBox.CheckedItems             Debug.Print(myitem.ToString())         NextEnd SubPrivate Sub ausgewählteElementeausgeben_M2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _         Handles ausgewählteElementeausgeben_M2.Click         For Each myitem As String In CheckedListBox.CheckedItems             Debug.Print(myitem)         NextEnd SubPrivate Sub ausgewählteElementeausgeben_M3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _         Handles ausgewählteElementeausgeben_M3.Click         For i = 0 To Me.CheckedListBox.Items.Count - 1             If CheckedListBox.GetItemChecked(i) = True Then                 Debug.Print(Me.CheckedListBox.Items.Item(i))             End If         NextEnd Sub

aktuell ausgewähltes Elemente ausgeben

Im Gegensatz zur CheckedItems-Eigenschaft gibt es in der CheckedListbox auch die Eigenschaft SelectedItems. Dabei handelt es sich um das aktuell selektierte Element (blau hinterlegt). Dieses muss nicht Bestandteil der CheckedItems sein. Eine Mehrfachauswahl ist jedoch bei der CheckedListbox nicht möglich. Daher erscheint die CheckedItems verwirrend, da es ein Plural darstellt. Aber egal. 

Grundsätzlich ist die CheckedListbox so eingestellt, dass man zwei Mal auf ein Listenelement klicken muss, damit es angehackt ist. Der erste Klick selektiert das Element (dh. es ist blau hinterlegt) und erst der Zweite setzt die Checked-Eigenschaft. Man kann dies jedoch unter den CheckedListbox Eigenschaften umstellen. Dafür ist die CheckOnClick Eigenschaft verantwortlich. Ist diese auf True gesetzt, dann reicht ein Klick auf das Element und sowohl die Eigenschaft Checked und Selected sind für das Element erfüllt. In diesem Fall ist das Selected Item Bestandteil der Checked Items.

aktuell ausgewähltes Element

Private Sub ausgewähltesElement_M1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _         Handles ausgewähltesElement_M1.Click         For Each myitem As String In CheckedListBox.SelectedItems             MsgBox(myitem)         NextEnd SubPrivate Sub ausgewähltesElement_M2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _         Handles ausgewähltesElement_M2.Click         MsgBox(Me.CheckedListBox.SelectedItem.ToString())End Sub

mehr Informationen zu einem Element speichern

Am Anfang mag man meist mit einer CheckedListBox auskommen. Aber was ist, wenn man zusätzliche Informationen zu einem Element speichern möchte. Dann könnte man das ganze irgendwie umbauen, aber das bedeutet meist viel Arbeit. Leute, die sich die Eigenschaften der CheckedListBox ansehen, werden vielleicht auch auf Multicolumn stoßen. Diese Eigenschaft bedeutet aber nicht, dass man mehr Informationen zu einem Element speichern kann, sondern lediglich, dass sobald eine Spalte voll ist, für weitere Elemente eine neue angelegt wird. Das ist übrigens bei der der normalen Listbox auch so. Ich würde das Thema nicht ansprechen, wenn es nicht doch eine Lösung gäbe. Das CheckedListBox-Steuerelement (Control) aktzeptiert jegliche Art von Objekten. Man braucht nur eine Klasse erstellen, die die entsprechenden Daten beinhaltet. Wichtig hierbei ist, dass die Funktion mittels overrides überschrieben wird, da das Element jetzt nicht nur einen String enthält.

Ein Beispiel: Will man die Elemente - wie oben - aus einer Textdatei einlesen, aber zusätzlich noch die Datei von der die Elemente stammen speichern, dann würde man eine zusätzliche Eigenschaft benötigen, die den Pfad der Datei speichert. Eine solche Klasse könnte beispielsweise so aussehen.

Klasse für das Objekt

Public Class MyListBoxItem     Private _name As String     Private _path As String      Public Property Name As String         Get             Return _name         End Get         Set(ByVal value As String)             _name = value         End Set     End Property      Public Property Path As String         Get             Return _path         End Get         Set(ByVal value As String)             _path = value         End Set     End Property      Public Overrides Function ToString() As String         Return Name     End FunctionEnd Class

Würde man nun die CheckedListBox mit den Informationen der jeweiligen Zeilen und der Pfade versorgen, könnte man das folgendermaßen machen:

TextDatei2CheckedListBox2

Private Sub TextDatei2CheckedListBox2(ByVal smyFile As String)         Dim objStreamReader As StreamReader = File.OpenText(smyFile)         Dim strLine As String = String.Empty          Do             strLine = objStreamReader.ReadLine()             If Len(Trim(strLine)) > 0 Then                 Dim newMyItem As New MyListBoxItem                 newMyItem.Name = strLine                 newMyItem.Path = smyFile                 'oder alternativ: CheckedListBox.Items.Add(New MyListBoxItem() With {.Name = strLine, .Pfad = smyFile})                 Me.CheckedListBox.Items.Add(newMyItem)             End If         Loop Until strLine Is Nothing          objStreamReader.Close()End Sub

Will man nun diese zusätzlich gespeicherten Informationen anzeigen, stellt sich die Frage nach dem Wie. Ich habe es nicht hinbekommen eine Kontextmenü zu den jeweiligen Einträgen anzuzeigen. Wenn man mir auf die Sprünge helfen kann, bitte gerne. Ich habe das schlussendlich über ein weiteres Formular gelöst, das die Daten anzeigt. 

Formular mit den Details

Public Class itemDetails      Public Sub New()          ' Dieser Aufruf ist für den Designer erforderlich.         InitializeComponent()          ' Fügen Sie Initialisierungen nach dem InitializeComponent()-Aufruf hinzu.      End Sub      Public Sub New(ByVal mlbi As MyListBoxItem)         InitializeComponent()         Me.txt_Name.Text = mlbi.Name         Me.txt_Pfad.Text = mlbi.Path     End SubEnd Class

Der Aufruf dieses Formulars erfolgt mittels Übergabe der Objektes. Vorher muss natürlich geprüft werden, ob das Element wirklich von dem Typ ist.

Formular öffnen

Private Sub CheckedListBox_MouseDoubleClick(ByVal sender As System.Object, _         ByVal e As System.Windows.Forms.MouseEventArgs) _         Handles CheckedListBox.MouseDoubleClick         If TypeOf (Me.CheckedListBox.SelectedItem) Is MyListBoxItem Then             Dim nF As itemDetails = New itemDetails(Me.CheckedListBox.SelectedItem)             nF.ShowDialog()         End IfEnd Sub

Liste leeren

Zu guter letzt möchte ich nicht unterwähnt lassen, wie man die Liste leeren kann. Hierfür gibt es grundsätzlich zwei Möglichkeiten.

Listenelemente löschen

Private Sub Listeleeren_M1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _         Handles Listeleeren_M1.Click         While Me.CheckedListBox.Items.Count > 0             Me.CheckedListBox.Items.Remove(CheckedListBox.Items(0))         End WhileEnd SubPrivate Sub Listeleeren_M2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _         Handles Listeleeren_M2.Click         For i As Integer = Me.CheckedListBox.Items.Count - 1 To 0 Step -1             Me.CheckedListBox.Items.RemoveAt(i)         Next i End Sub

Selbiges funktioniert auch für alle angehackten Elemente:

angekackte Elemente löschen

Private Sub angehackteElementelöschen_M1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles angehackteElementelöschen_M1.Click         While Me.CheckedListBox.CheckedItems.Count > 0             Me.CheckedListBox.Items.Remove(CheckedListBox.CheckedItems(0))         End WhileEnd SubPrivate Sub angehackteElementelöschen_M2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles angehackteElementelöschen_M2.Click         For i As Integer = Me.CheckedListBox.CheckedItems.Count - 1 To 0 Step -1             Me.CheckedListBox.Items.RemoveAt(Me.CheckedListBox.CheckedIndices(i))         NextEnd Sub

Und natürlich auch für das aktuell ausgewählte Element

ausgewähltes Element löschen

Private Sub ausgewähltesElementlöschen_M1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ausgewähltesElementlöschen_M1.Click         Me.CheckedListBox.Items.RemoveAt(Me.CheckedListBox.SelectedIndex)End SubPrivate Sub ausgewähltesElementlöschen_M2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ausgewähltesElementlöschen_M2.Click         Me.CheckedListBox.Items.Remove(Me.CheckedListBox.SelectedItem)End Sub

Speichern

Ich hätte fast das Speichern vergessen. Also einmal als Speichern unter bereits vorhanden Dateinamen (Variable: myfile) und einmal als Speichern unter.

Speichern & Speichern unter

Private Sub SpeichernToolStripMenuItem_Click(ByVal sender As _         System.Object, ByVal e As System.EventArgs) _         Handles SpeichernToolStripMenuItem.Click         Dim objStreamWriter As StreamWriter = New StreamWriter(myfile, False)         For Each item As String In Me.CheckedListBox.Items             objStreamWriter.WriteLine(item)         Next         objStreamWriter.Close()End SubPrivate Sub SpeichernunterToolStripMenuItem_Click(ByVal sender As _         System.Object, ByVal e As System.EventArgs) _         Handles SpeichernunterToolStripMenuItem.Click         Dim sfd As New SaveFileDialog         sfd.FileName = myfile         If sfd.ShowDialog = DialogResult.OK Then             myfile = sfd.FileName             Dim objStreamWriter As StreamWriter = New StreamWriter(myfile, False)             For Each item As String In Me.CheckedListBox.Items                 objStreamWriter.WriteLine(item)             Next             objStreamWriter.Close()         End IfEnd Sub