Translate

Montag, 2. Januar 2017

ACCESS: Markierung geht in ListBox mit Multiselect (extended) Einstellung verloren!

Das Access-Steuerelement ListBox in einem Formular ist dazu da Einträge in einer Listenform darzustellen. Diese Einträge lassen sich auswählen/markieren.
Die Markierten Einträge können in VBA über die Auflistung ItemsSelected ausgewertet werden.
Über die Eigenschaft "Mehrfachauswahl/MultiSelect" kann eingestellt werden ob ein Benutzer immer nur einen Eintrag oder mehrerer auswählen kann.
Die dritte Option "Erweitert" welches den Wert 2 entspricht ist leider Buggy!
Die Markierung gehen teilweise verloren, sobald das Listenfeld den Fokus verliert.

Folgendermaßen kann der Fehler reproduziert werden:
- Mit der Maus ziehen und dabei einige Einträge in der ListBox markieren
- Einen oder mehrere Einträge nachträglich abwählen mit Hilfe der gedrückten STRG-Taste
- Wenn die ListBox nun den Fokus verliert (z.B durch Klick auf ein anderes Feld) sind alle Einträge unterhalb des ersten abgewählten Eintrages nicht mehr markiert.

Das Problem ist lediglich in der Anzeige, die Auflistung ItemsSelected  enthält weiterhin die korrekt ausgewählten Einträge!

Aus Benutzersicht sind die Eintrage jedoch nicht mehr markiert, was sehr verwirrend ist. Die Anzeige ist somit schlichtweg falsch!

Das sollten wir schnellstmöglich lösen, und zwar in dem wir beim Fokusverlust der ListBox einfach die ausgewählten Einträge per VBA einfach nochmal explizit auswählen lassen. Das geht, weil ja nur die Anzeige falsch ist, die Auflistung ItemsSelected  ist weiterhin korrekt.

Somit löst die folgende Prozedur den kleinen aber sehr unschönen Bug:
Private Sub Liste_LostFocus()
    Dim itm As Variant
   
    For Each itm In Me.Liste.ItemsSelected
        Me.Liste.Selected(itm) = False
        Me.Liste.Selected(itm) = True
    Next
End Sub

Anmerkung: Sollten sehr viele Einträge ausgewählt sein, kann die Schleife zu Verzögerungen führen.

Ein kleines Beispiel zur Veranschaulichung kann hier heruntergeladen werden.
Dort habe ich auch die Lösung in einer Klasse gekapselt, so dass die Klasse selbstständig für alle ListBoxen im Formular die Korrektur vornimmt.

Somit reduzieren sich die Anweisungen pro Formular auf ein Minimum:
   
Dim cCorrectionControls As clsCorrectionControls
Private Sub Form_Load()
    Set cCorrectionControls = New clsCorrectionControls

    cCorrectionControls.SetForm = Me
End Sub


Das Jahr fängt ja gut an!

Keine Kommentare:

Kommentar veröffentlichen