none
Benutzerdefinierte Combobox/Listbox RRS feed

  • 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.Name

    Soweit 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

    Dienstag, 22. Januar 2013 16:42

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

    Dienstag, 22. Januar 2013 18:32
    Beantworter
  • 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

    Mittwoch, 23. Januar 2013 14:13
    Beantworter

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


    Dienstag, 22. Januar 2013 17:36
  • 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

    Dienstag, 22. Januar 2013 18:32
    Beantworter
  • Hallo,

    ich dachte auch, mit Overrides weiterzukommen. Allerdings - und das ist mein Problem - weiß ich nicht, welches Event ich überschreiben soll, damit  .Items.Add abgefangen und mein eigener Code ausgeführt wird.

    Vielen Dank.

    Michael

    Mittwoch, 23. Januar 2013 08:23
  • 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

    Mittwoch, 23. Januar 2013 08:27
  • 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

    Mittwoch, 23. Januar 2013 14:13
    Beantworter
  • Sei bedankt, Elmar. Auch für die Links, die erstmal genug Lesestoff bieten.

    Viele Grüße

    Michael

    Mittwoch, 23. Januar 2013 14:33