[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