Benutzer mit den meisten Antworten
Benutzerdefinierte Combobox/Listbox

Frage
-
Hallo zusammen,
ich befinde mich in der Experimentierphase mit Visual Basic 2012 und versuche gerade, mich vom alten Visual Basic 6 zu lösen.
Im Moment beschäftige ich mich damit, wie man eigene Steuerelemente erstellt.
Es handelt sich nicht um von Grund auf neu erstellte und selbst gezeichnete Steuerelemente, sondern lediglich um einige Eigenschaften erweiterte Versionen der Visual Studio-eigenen Controls.
Als Beispiel dient die Combobox, die in Visual Studio, warum auch immer, keine ItemData-Eigenschaft mehr aufweist. Diese wollte ich ihr hinzufügen.
Ich habe eine Klasse erstellt, welche die ItemData-Eigenschaft als Property aufweist (Zuweisung und Rückgabe eines Integer-Wertes).
Wenn ich in einer normalen Windows Forms-Anwendung eine Visual Studio-Combobox auf eine Form zeichne und diesem Projekt die erwähnte Klasse (im Beispiel heißt sie "myClass") hinzufüge, kann ich die ItemData-Eigenschaft wie folgt setzen:
Combobox.Items.Add (New myClass("Januar",1)
Combobox.Items.Add (New myClass("Februar",2)
Combobox.Items.Add (New myClass("März",3)
Der erste Parameter ("Januar", "Februar," "März") wird in der Membervariablen "Name", der zweite (1,2,3) in der Membervariablen "ItemData" gespeichert. Die Klasse hat zwei Eigenschaften mit denselben Namen.
Die Abfrage der ItemData-Eigenschaft geschieht somit über:
myClass = ComboBox1.Items(ComboBox1.SelectedIndex)
MsgBox myClass.ItemData & " " & myClass.NameSoweit so gut.
Jetzt stehe ich vor der Situation, dies in einem eigenen Steuerelement zu nachzubilden, habe aber keine Ahnung, wie.
Erst dachte ich, ich müsse im benutzerdefinierten Steuerelement das .Items.Add-Event überschreiben, aber das gibt es wohl nicht (ich dachte da an ein OnItemsAdd-Event oder ähnliches).
Oder muß ich eine eigene Methode programmieren, die dann eben nicht .Items.Add heißt, sondern zum Beispiel "AddItems" und diese dann statt .Items.Add verwenden? In dem Fall wäre aber immer noch die Gefahr, daß jemand anderes, der das Control verwendet, weiterhin .Items.Add nimmt.
Also, langes Gerede - kurzer Sinn: gibt es eine Möglichkeit, die .Items.Add-Methode in einer benutzerdefinierten Combo-/Listbox abzufangen und eigenen Programmcode unterzubringen?
Ich hoffe, ich konnte mich einigermaßen erklären.
Vielen Dank und viele Grüße
Michael
Antworten
-
Hallo Michael,
für den Umstieg empfehle ich Dir jeweils genauer hinzugucken, was es in .NET "Neues" gibt - naja, einiges schon mehr als 10 Jahre. Vieles muss man nicht mehr machen, weil es das schon gibt, bzw. mit geringerem Aufwand zu machen ist.
Um eine ComboBox mit Monatsnummer und -namen darzustellen braucht es keiner größeren Erweiterungen.
Über die Datenbindung kann man dies über eine Auflistung und die Datenbindung erledigen.
Die ComboBox bietet über ihre Eigenschaften wie SelectedValue und SelectedItem direkt Zugriff auf die Werte.' auf Basis der aktuellen Kultur (ggf. auch CurrentUICulture) Dim dfi = System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat ' Array mit Nummer und Name ' Verwendet Tuple anstatt eigener Klasse, alternativ KeyValuePair(Of Integer, String) Dim monthIndexNames = New Tuple(Of Integer, String)(dfi.Calendar.GetMonthsInYear(Date.Today.Year) - 1) {} ' Konventionelle Schleife (alternativ LINQ) For index = 0 To monthIndexNames.Length - 1 monthIndexNames(index) = (Tuple.Create(index + 1, dfi.MonthNames(index))) Next Me.monthComboBox.DropDownStyle = ComboBoxStyle.DropDownList Me.monthComboBox.DataSource = monthIndexNames Me.monthComboBox.DisplayMember = "Item2" ' hier Name Me.monthComboBox.ValueMember = "Item1" ' hier Index / Wert ' Für die Anzeige (konvetionell via Handles geht natürlich auch) AddHandler Me.monthComboBox.SelectedValueChanged, Sub(sender, e) Dim control = DirectCast(sender, ComboBox) Console.WriteLine( "Monat: {0} / '{1}'", control.SelectedValue, CType(control.SelectedItem, Tuple(Of Integer, String)).Item2) End Sub
Das Abfüllen der Monatsnamen habe ich oben über die Kultur-Informationen erledigt, die .NET eingebaut hat. Der Rest ist besteht aus dem Zuweisen der Auflistung sowie des Value- und DisplayMember. Das Ereignis - hier über ein Lambda - zeigt den Auswahlwechsel an.
Anstatt der Tuple-Klasse könnte man auch eine eigene Klasse oder aber KeyValuePair(Of K, V) verwenden - dann wären die generischen Namen Item1 und Item2 auch weg.
Das Vorgehen bliebt gleich, wenn Du andere Daten als Auswahl anzeigen wolltest, z. B. Daten aus einer Datenbank etc. Anstatt eines Arrays oder einer Auflistung kann auch eine DataTable uam. verwendet werden.
Gruß Elmar
- Als Antwort markiert Bayer, Michael Mittwoch, 23. Januar 2013 14:34
-
Hallo Michael,
ich bastele schon seit gut zehn Jahren an .NET herum, insofern habe ich da etwas Vorsprung ;)
Primäre Anlaufstelle wäre immer noch MSDN: Entwicklungshandbuch für .NET Framework
Alles lesen wird man in kurzer Ziet nicht können. Aber man sollte sich vor den einen besonders interessierenden Technologien (wie hier Windows Forms) gerade am Anfang den Basisgrundlagen Aufmerksamkeit schenken: Grundlagen der .NET Framework-Anwendung - Zeichenketten, Formatieren sowie Generika und Auflistungen, Streams usw. braucht man tagtäglich.
An Visual Basic Classic Umsteiger sei (wie immer) der Rat gegeben, grundsätzlich mit den Einstellungen zu arbeiten:
Option Explicit On Option Infer On Option Strict On
Leider bis heute keine Standard-Einstellung, kann (und sollte) man aber in den Optionen ändern. Gerade Option Strict On vermeidet viele Unsauberkeiten die VB ansonsten aus historischen Gründen erlaubt.
Auch auf die aktuellen Sprachfeatures solltest Du ein Blick werfen, denn da hat sich im Lauf der Jahre einiges getan (Ich hatte z. B. LINQ für das Abfüllen des Array durch "konventionellen" Code ersetzt, um nicht zu viele Fragezeichen zu provozieren).
Was Tuple angeht: Das war nur weil die bequem verfügbar sind. Da sie relativ neu (.NET 4.0) ist, verwende ich normalerweise eigene Klassen, wie häufig ein IdName für ComboBoxen - die Alternative mit KeyValuePair hatte ich im Kommentar angeführt. (Vermeiden sollten man "Krücken" wie Object (entspräche Variant) für alles und das Ankleistern über Tag Eigenschaften, wie es bei VB Classic häufig gemacht wurde - denn .NET ist ein richtiges OO Framework).
Gruß Elmar
- Als Antwort markiert Bayer, Michael Mittwoch, 23. Januar 2013 14:33
Alle Antworten
-
Servus Michael
suchst du zufällig nach Overrides ...
z.B. wenn du einen abgeleitet Klasse verwendest und du zb die Refresh überschreiben willst, dann könnte das so aussehen
Public Overrides Sub refresh()
... dein code
mfg eem monarch
- Bearbeitet Monarch-Falter Dienstag, 22. Januar 2013 17:37
-
Hallo Michael,
für den Umstieg empfehle ich Dir jeweils genauer hinzugucken, was es in .NET "Neues" gibt - naja, einiges schon mehr als 10 Jahre. Vieles muss man nicht mehr machen, weil es das schon gibt, bzw. mit geringerem Aufwand zu machen ist.
Um eine ComboBox mit Monatsnummer und -namen darzustellen braucht es keiner größeren Erweiterungen.
Über die Datenbindung kann man dies über eine Auflistung und die Datenbindung erledigen.
Die ComboBox bietet über ihre Eigenschaften wie SelectedValue und SelectedItem direkt Zugriff auf die Werte.' auf Basis der aktuellen Kultur (ggf. auch CurrentUICulture) Dim dfi = System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat ' Array mit Nummer und Name ' Verwendet Tuple anstatt eigener Klasse, alternativ KeyValuePair(Of Integer, String) Dim monthIndexNames = New Tuple(Of Integer, String)(dfi.Calendar.GetMonthsInYear(Date.Today.Year) - 1) {} ' Konventionelle Schleife (alternativ LINQ) For index = 0 To monthIndexNames.Length - 1 monthIndexNames(index) = (Tuple.Create(index + 1, dfi.MonthNames(index))) Next Me.monthComboBox.DropDownStyle = ComboBoxStyle.DropDownList Me.monthComboBox.DataSource = monthIndexNames Me.monthComboBox.DisplayMember = "Item2" ' hier Name Me.monthComboBox.ValueMember = "Item1" ' hier Index / Wert ' Für die Anzeige (konvetionell via Handles geht natürlich auch) AddHandler Me.monthComboBox.SelectedValueChanged, Sub(sender, e) Dim control = DirectCast(sender, ComboBox) Console.WriteLine( "Monat: {0} / '{1}'", control.SelectedValue, CType(control.SelectedItem, Tuple(Of Integer, String)).Item2) End Sub
Das Abfüllen der Monatsnamen habe ich oben über die Kultur-Informationen erledigt, die .NET eingebaut hat. Der Rest ist besteht aus dem Zuweisen der Auflistung sowie des Value- und DisplayMember. Das Ereignis - hier über ein Lambda - zeigt den Auswahlwechsel an.
Anstatt der Tuple-Klasse könnte man auch eine eigene Klasse oder aber KeyValuePair(Of K, V) verwenden - dann wären die generischen Namen Item1 und Item2 auch weg.
Das Vorgehen bliebt gleich, wenn Du andere Daten als Auswahl anzeigen wolltest, z. B. Daten aus einer Datenbank etc. Anstatt eines Arrays oder einer Auflistung kann auch eine DataTable uam. verwendet werden.
Gruß Elmar
- Als Antwort markiert Bayer, Michael Mittwoch, 23. Januar 2013 14:34
-
Hallo Elmar,
vielen Dank für Deine Antwort. Das Befüllen der Combobox mit Monatsname und -nummer war nur als Beispiel gedacht, aber wie Du ja schreibst, kann diese Methode auch für andere Daten verwendet werden.
Ich bin, wie gesagt, völliger Neuling in Sachen .net. Woher bekommt man denn solche Informationen? Wo liest Du nach bzw. wie bist Du auf diese Idee mit "Tuple" als Ersatz für ItemData gekommen?
Viele Grüße
Michael
-
Hallo Michael,
ich bastele schon seit gut zehn Jahren an .NET herum, insofern habe ich da etwas Vorsprung ;)
Primäre Anlaufstelle wäre immer noch MSDN: Entwicklungshandbuch für .NET Framework
Alles lesen wird man in kurzer Ziet nicht können. Aber man sollte sich vor den einen besonders interessierenden Technologien (wie hier Windows Forms) gerade am Anfang den Basisgrundlagen Aufmerksamkeit schenken: Grundlagen der .NET Framework-Anwendung - Zeichenketten, Formatieren sowie Generika und Auflistungen, Streams usw. braucht man tagtäglich.
An Visual Basic Classic Umsteiger sei (wie immer) der Rat gegeben, grundsätzlich mit den Einstellungen zu arbeiten:
Option Explicit On Option Infer On Option Strict On
Leider bis heute keine Standard-Einstellung, kann (und sollte) man aber in den Optionen ändern. Gerade Option Strict On vermeidet viele Unsauberkeiten die VB ansonsten aus historischen Gründen erlaubt.
Auch auf die aktuellen Sprachfeatures solltest Du ein Blick werfen, denn da hat sich im Lauf der Jahre einiges getan (Ich hatte z. B. LINQ für das Abfüllen des Array durch "konventionellen" Code ersetzt, um nicht zu viele Fragezeichen zu provozieren).
Was Tuple angeht: Das war nur weil die bequem verfügbar sind. Da sie relativ neu (.NET 4.0) ist, verwende ich normalerweise eigene Klassen, wie häufig ein IdName für ComboBoxen - die Alternative mit KeyValuePair hatte ich im Kommentar angeführt. (Vermeiden sollten man "Krücken" wie Object (entspräche Variant) für alles und das Ankleistern über Tag Eigenschaften, wie es bei VB Classic häufig gemacht wurde - denn .NET ist ein richtiges OO Framework).
Gruß Elmar
- Als Antwort markiert Bayer, Michael Mittwoch, 23. Januar 2013 14:33