Autovervollständigung in Combobox

  • VB.NET

Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von Gloem.

    Autovervollständigung in Combobox

    Hallo,

    mir reicht die Autovervollständigung die Visual Studio mitliefert leider nicht aus. Ich möchte das er nicht nur die Werte in der Auswahl anzeigt die mit dem eingegebenen Zeichen änfängt sondern alle, die die Zeichen an irgendweiner Stelle beinhaltet. Mein Lösungsansatz ging hierbei über eine AutoCompleteStringCollection in der nur die passenden einträge ausgewählt werden:

    VB.NET-Quellcode

    1. Private Sub Com_Gemarkung_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Com_Gemarkung.TextChanged
    2. Dim entry As System.Collections.Generic.KeyValuePair(Of String, String)
    3. Dim autoComSource As New Windows.Forms.AutoCompleteStringCollection
    4. For Each entry In gemarkungen
    5. If (entry.Key.Contains(Com_Gemarkung.Text)) Then
    6. autoComSource.Add(entry.Key)
    7. End If
    8. Next
    9. Com_Gemarkung.AutoCompleteCustomSource = autoComSource
    10. Com_Gemarkung.AutoCompleteSource = AutoCompleteSource.CustomSource
    11. Com_Gemarkung.AutoCompleteMode = AutoCompleteMode.SuggestAppend
    12. End Sub


    Aus irgendeinem Grund bekomm ich aber immer an Ende dieser Funktion eine AccessViolationException und ich hab keine Ahnung warum. Vielleicht kann mir ja jemand weiterhelfen oder mir sagen dass mein Ansatz komplett verkehrt ist

    System.AccessViolationException wurde nicht behandelt.
    Message="Es wurde versucht, im geschützten Speicher zu lesen oder zu schreiben. Dies ist häufig ein Hinweis darauf, dass anderer Speicher beschädigt ist."
    Source="System.Windows.Forms"
    StackTrace:
    bei System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
    bei System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
    bei System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
    bei System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
    bei System.Windows.Forms.Application.Run(ApplicationContext context)
    bei Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
    bei Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
    bei Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
    bei GemarkungsAuskunftSystem.My.MyApplication.Main(String[] Args) in 17d14f5c-a337-4978-8281-53493378c1071.vb:Zeile 81.
    bei System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
    bei System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
    bei Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
    bei System.Threading.ThreadHelper.ThreadStart_Context(Object state)
    bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
    bei System.Threading.ThreadHelper.ThreadStart()
    InnerException:
    hallo golem,

    mit
    Hilfe

    kommst du hier nicht weiter.

    was genau willst du eigentlich erreichen ?
    was heisst das genau ?
    mir reicht die Autovervollständigung die Visual Studio mitliefert leider nicht aus.

    gruss

    mikeb69
    Ich möchte das er nicht nur die Werte in der Auswahl anzeigt die mit dem eingegebenen Zeichen änfängt sondern alle, die die Zeichen an irgendweiner Stelle beinhaltet
    Die Autovervollständigung einer Combobox die Visual Basic standardmäßig anbietet, ermöglicht leider nur die Vervollständigung von Werten solange die ersten Zeichen bekannt sind. Sprich aus "Vi" wird als Vorschlag "Visual Basic 2008" und "Visual Basic" vorgeschlagen falls bekannt, aber leider nicht "Basic".

    Ich möchte diese Vorschläge nun auch um die Werte erweitern die den Wert beinhalten, sprich bei Eingabe von "Bas" soll "Visual Basic 2008", "Visual Basic" und "Basic"

    Mein Lösungsansatz ging hierbei über eine AutoCompleteStringCollection in der nur die passenden einträge ausgewählt werden:

    VB.NET-Quellcode

    1. Private Sub Com_Gemarkung_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Com_Gemarkung.TextChanged
    2. Dim entry As System.Collections.Generic.KeyValuePair(Of String, String)
    3. Dim autoComSource As New Windows.Forms.AutoCompleteStringCollection
    4. For Each entry In gemarkungen
    5. If (entry.Key.Contains(Com_Gemarkung.Text)) Then
    6. autoComSource.Add(entry.Key)
    7. End If Next
    8. Com_Gemarkung.AutoCompleteCustomSource = autoComSource
    9. Com_Gemarkung.AutoCompleteSource = AutoCompleteSource.CustomSource
    10. Com_Gemarkung.AutoCompleteMode = AutoCompleteMode.SuggestAppend
    11. End Sub


    Aus irgendeinem Grund bekomm ich aber immer an Ende dieser Funktion eine AccessViolationException und ich hab keine Ahnung warum. Vielleicht kann mir ja jemand weiterhelfen oder mir sagen dass mein Ansatz komplett verkehrt ist
    hallo gloem,

    eine AccessViolationException bekommt man oft, wenn man api's mit den falschen variablentypen deklariert - aber das trifft hier wohl nicht zu.
    wenn man in google sucht, findet man diese meldung in verbindung mit usercontrols.

    was ist Com_Gemarkung genau - eine normale textbox ?

    was mir am deinem code auch aufgefallen ist, du instanziertst deine autocomplete klasse genau dann wann sie eigentlich in aktion treten soll.
    auch die zuweisung

    VB.NET-Quellcode

    1. Com_Gemarkung.AutoCompleteCustomSource = autoComSource

    sollte eher im form_load ereignis stehen.

    gruss

    mikeb69
    Danke für die Antwort

    Com_Gemarkung ist eine ComboBox

    Die Combobox wird zuerst im Load-Ereignis mit allen Daten gefüllt. Auch wird AutoCompleteSource auf ListItems gesetzt und AutocompleteMode auf SuggestAppend

    Sobald jemand nun eine Taste drückt soll aus allen möglichen Werten die ausgesucht werden, in denen das(die) entsprechende Zeichen(en) an irgendeiner Stelle vorkommt. Die möglichen Treffer speicher ich dann in einer AutoCompleteStringCollection und weise die als CustomSource der ComboBox zu.

    Wo ich das hier gerade schreibe fällt mir auf, dass AutoCompleteMode nach aktivieren der CustomSource nicht mehr auf SuggestAppend stehen darf, da ja jetzt nicht mehr nur auf die Anfangszeichen geachtet werden soll
    hallo gloem,

    wie gesagt, ich glaube das dass textchanged ereignis der falsche ort ist.
    dies wird immer ausgelöst, wenn deine combobox den focus hat und der user eine taste drückt.

    eigentlich der ort für die autovervollständigung.
    du jedoch erstellst hier deine liste und weist diese zu - hab da zwar wenig ahnung - aber so kann es meiner meinung nicht klappen.

    setz mal das füllen der autocompleteliste und das zuweisen auf einen früheren zeitpunkt. z.b. form_load

    gruss

    mikeb69
    Aber das Programm soll ja je nach neu eingegebenen Zeichen in der ComboBox eine NEUE AutoCompleteListe verwenden, da nur max. 8 Vorschläge angezeigt werden sollen und Einträge ohne die eingegebenen Zeichen nicht auswählbar sein sollen. Von daher wäre das TextChanged-Ereigniss doch das richtige um die Liste zu füllen.


    Liste vorher:
    Visual Basic 2008
    Visual Basic
    Basic
    Java
    C
    ++

    Ursprungliches Verhalten bei Eingabe von V:
    Liste wird beibehalten
    Vorschläge vom Programm:
    Visual Basic 2008
    Visual Basic


    Ursprungliches Verhalten bei Eingabe von Vi:
    Liste wird beibehalten
    Vorschläge vom Programm:
    Visual Basic 2008
    Visual Basic


    Ursprungliches Verhalten bei Eingabe von B:
    Liste wird beibehalten
    Vorschläge vom Programm:
    Basic


    Neues Verhalten bei Eingabe von V:
    Liste wird bearbeitet(da nur max 8 Vorschläge angezeigt werden sollen):
    Visual Basic 2008
    Visual Basic

    Java
    Vorschläge vom Programm:
    Visual Basic 2008
    Visual Basic

    Java

    Neues Verhalten bei Eingabe von B:
    Liste wird bearbeitet(da nur max 8 Vorschläge angezeigt werden sollen):
    Visual Basic 2008
    Visual Basic
    Basic

    Vorschläge vom Programm:
    Visual Basic 2008
    Visual Basic

    Basic
    ich denke mal dass das nicht wirklich so möglich ist, weil VB ja aus der neuen Liste trotzdem nur die seiner Meinung nach passenden Elemente reinbringt.
    Wenn du die Sachen in ner Combobox bringen willst, so hab ich das jetzt verstanden, kannst du ja vielleicht die Combobox neu belegen und befüllen (deine Einträge mit Contains oder ähnlichen überprüfen)
    Das mach ich ja hier:

    VB.NET-Quellcode

    1. Dim autoComSource As New Windows.Forms.AutoCompleteStringCollection
    2. For Each entry In gemarkungen
    3. If (entry.Key.Contains(Com_Gemarkung.Text)) Then
    4. autoComSource.Add(entry.Key)
    5. End If
    6. Next



    Ich habe alle möglichen Einträge in einem SortedSet(wird noch für was anderes benötigt) gespeichert und überprüfe je nach eingegebenen Zeichen (Com_Gemarkung.text) ob der Schlüssel diese Zeichen enthält. Wenn ja wird er der AutoCompleteStringCollection hinzugefügt.
    Habs erstmal so weit geändert und das mit der CustomListe weggelassen:

    VB.NET-Quellcode

    1. Private Sub Com_Gemarkung_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Com_Gemarkung.TextChanged
    2. Com_Gemarkung.Items.Clear()
    3. ' Setzen der Autovervollständigung in der Combobox
    4. Com_Gemarkung.AutoCompleteMode = AutoCompleteMode.None
    5. Com_Gemarkung.AutoCompleteSource = AutoCompleteSource.None
    6. Dim entry As System.Collections.Generic.KeyValuePair(Of String, String)
    7. Dim autoComSource As New Windows.Forms.AutoCompleteStringCollection
    8. For Each entry In gemarkungen
    9. If (entry.Key.ToLower.Contains(Com_Gemarkung.Text.ToLower)) Then
    10. Com_Gemarkung.Items.Add(entry.Key)
    11. End If
    12. Next
    13. End Sub


    Jetzt schreibt der mir die übriggebliebenen Einträge in die Combobox. Wenn ich dort aber was eingeben fügt der das neue Zeichen links an die vorhandenen Zeichen an, anstatt wie in Europa üblich rechts. Kann man das durch eine Eigenschaft der Combobox ändern oder muss man das durch Quellcode machen?