WPF Textbox Vorschläge mithilfe einer ObservableCollection und ViewModel

  • WPF

Es gibt 4 Antworten in diesem Thema. Der letzte Beitrag () ist von Schwakowiak.

    WPF Textbox Vorschläge mithilfe einer ObservableCollection und ViewModel

    Hallo liebe Leute,
    ich habe eine WPF-Anwendung, in der eine Textbox vorhanden ist (In diese wird eine Materialnummer eingebgen.)

    In der Klasse Materialnummern sollen die Werte gespeichert werden.

    VB.NET-Quellcode

    1. Public Class Materialnummern
    2. Private _Materialnummer As String
    3. Public Property Materialnummer As String
    4. Get
    5. Return _Materialnummer
    6. End Get
    7. Set(ByVal value As String)
    8. _Materialnummer = value
    9. End Set
    10. End Property
    11. Private _Materialbezeichnung As String
    12. Public Property Materialbezeichnung As String
    13. Get
    14. Return _Materialbezeichnung
    15. End Get
    16. Set(ByVal value As String)
    17. _Materialbezeichnung = value
    18. End Set
    19. End Property
    20. End Class


    Also nur zwei Propertys.
    In der Klasse DATA werden die Daten geladen und eine ObservableCollection der Materialnummern zurück gegeben.
    Diese Daten werden mithilfe eines Typisierten DataSets geladen und die Klasse gefüllt (Funktioniert soweit auch.)

    VB.NET-Quellcode

    1. Imports System.Collections.Generic
    2. Imports System.Collections.ObjectModel
    3. Imports System.Data
    4. Public Class Data
    5. Private Nummern As New ObservableCollection(Of Materialnummern)
    6. Private Sub LadeDatenAusDatenbank()
    7. Dim adapter As New stammDataSetTableAdapters.MaterialstammTableAdapter()
    8. Dim ds As New stammDataSet.MaterialstammDataTable
    9. adapter.Fill(ds)
    10. For Each x As DataRow In ds.Rows
    11. Nummern.Add(New Materialnummern With {
    12. .Materialbezeichnung = x("Materialkurztext").ToString(),
    13. .Materialnummer = x("Material").ToString()})
    14. Next
    15. End Sub




    Nun wollte ich eine Klasse (z.B. MaterialnummernViewModel) erstellen, in der diese Daten geladen (Aufgerufen) werden, und an eine Property namens MaterialnummernListeView gebunden werden. Diese Liste soll eine ICollectionView sein, die ich später an
    die WPF anbinden möchte.

    Ob das Sinnig ist, nun das Frage ich euch.
    Wenn ich eine Referenznummer eingebe, dauert es recht lange und ich bekomme eine sehr lange Liste mit Referenznummern.


    VB.NET-Quellcode

    1. Imports System.Collections.ObjectModel
    2. Imports System.ComponentModel
    3. Public Class MaterialnummernViewModel
    4. Dim laden As New Data()
    5. Private _MaterialnummernListe As New ObservableCollection(Of Materialnummern)
    6. Public Property MaterialnummernListe As ObservableCollection(Of Materialnummern)
    7. Get
    8. Return _MaterialnummernListe
    9. End Get
    10. Set(ByVal value As ObservableCollection(Of Materialnummern))
    11. _MaterialnummernListe = value
    12. End Set
    13. End Property
    14. Private _MaterialnummernListeView As ICollectionView
    15. Public Property MaterialnummernListeView As ICollectionView
    16. Get
    17. Return _MaterialnummernListeView
    18. End Get
    19. Set(ByVal value As ICollectionView)
    20. _MaterialnummernListeView = value
    21. End Set
    22. End Property
    23. Public Sub New()
    24. _MaterialnummernListe = laden.LadeDaten()
    25. Me._MaterialnummernListeView = CollectionViewSource.GetDefaultView(_MaterialnummernListe)
    26. End Sub
    27. End Class




    Nun meine Frage:
    Wie binde ich das ganze Nett an WPF? (Vielleicht Popup unter der Textbox?) und wie würde ich es besser machen bzw wie erstelle ich das ViewModel korrekt?
    Wie filtere ich diese Liste sobald meine Eingabelänge >=4 ist ( Dann erst gefiltert anzeigen)
    Zweispaltig (Links Referenznummer und rechts die Materialbezeichnung) ListView anstatt PopUp o.ä.?

    Vielen Dank :)
    Hallo

    Das sind viele Frage auf einmal. Zunächst solltest du mal zusehen das du ein korrektes ViewModel erstellst für das View welches du gerade verwenden willst.

    Schwakowiak schrieb:

    Wenn ich eine Referenznummer eingebe, dauert es recht lange und ich bekomme eine sehr lange Liste mit Referenznummern.

    Warum wenn du eine Referenznummer eingibst. Die Daten werden ja bereits beim instanzieren des ViewModels geladen und befinden sich im Speicher. Wenn du eine Referenznummer eingibst sollte ja nur noch gefiltert werden. Sehe ich das richtig? Um wieviele Referenznummer geht es hier/kann es hier gehen???

    Schwakowiak schrieb:

    Wie binde ich das ganze Nett an WPF? (Vielleicht Popup unter der Textbox?) und wie würde ich es besser machen bzw wie erstelle ich das ViewModel korrekt?

    Wäre hier nicht am besten eine AutoCompletetextbox??? z.b. aus dem WPFToolkit.

    Schwakowiak schrieb:

    Wie filtere ich diese Liste sobald meine Eingabelänge >=4 ist ( Dann erst gefiltert anzeigen)

    Eine ICollectionview wie du sie ja bereits erstellt hast ist ideal für das Filtern von Daten geeignet. Hier kannst du auch sehr schön entscheiden nach wievielen Zeichen die Filterung gestartet werden soll.
    Weitere Infos findest du hier sehr schön und kurz erklärt.

    Um jetzt hier nicht ZU weit ausholen zu müssen check dir das mal anhand der Infos und dann sehen wir weiter solltest du an einem Punkt nicht weiterkommen.
    Versuche mal die AutocompleteBox einzubinden und die Daten in diese zu bekommen, dann versuche dynamisch zu Filtern.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.
    Hallo Sascha,
    vielen Dank für deine Antwort.
    Vorne Weg, ich habe
    eine etwas andere Lösung gefunden. Ich nutze nun eine ListCollectionView
    mit dem PopUp. In diesem PopUp befindest sich ein ListView mit einer
    GridView.
    Klappt soweit ganz gut. Das ganze habe ich allerdings nicht
    über meine Klasse MaterialnummernViewModel hinbekommen, da ich nicht
    weiß, wie das mit den Filtern von statten gehen soll.

    Die Textbox
    (Eingabe) ist an die Property Referenznummer gebunden. Sobald eine
    aktualisierung (INotifyPropertyChanged) stattfindet, aktualisiere ich
    die ListCollection View

    VB.NET-Quellcode

    1. #Region "Propertys"
    2. 'andere propertys...
    3. Private _Referenznummer As String
    4. Public Property Referenznummer As String
    5. Get
    6. Return _Referenznummer
    7. End Get
    8. Set(ByVal value As String)
    9. _Referenznummer = value
    10. MView.Refresh() 'Hier das aktualisieren der ListCollectionView
    11. OnPropertyChanged("Referenznummer")
    12. End Set
    13. End Property
    14. Private _Nummern As New ObservableCollection(Of Materialnummern)
    15. Public Property Nummern As ObservableCollection(Of Materialnummern)
    16. Get
    17. Return _Nummern
    18. End Get
    19. Set(ByVal value As ObservableCollection(Of Materialnummern))
    20. _Nummern = value
    21. OnPropertyChanged("Nummern")
    22. End Set
    23. End Property
    24. Private _MView As ListCollectionView
    25. Public Property MView() As ListCollectionView
    26. Get
    27. Return _MView
    28. End Get
    29. Set(ByVal value As ListCollectionView)
    30. _MView = value
    31. OnPropertyChanged("MView")
    32. End Set
    33. End Property
    34. Private laden As New Data()
    35. #End Region


    Zu Beginn des Programms lade ich die Daten und Binde sie

    VB.NET-Quellcode

    1. Public Sub new()
    2. Nummern = laden.LadeDaten()
    3. MView = CType(CollectionViewSource.GetDefaultView(Nummern), ListCollectionView)
    4. MView.Filter = New Predicate(Of Object)(AddressOf IstReferenznummervorhanden)
    5. MView.Refresh()
    6. 'Weiteres Programm .....
    7. End Sub
    8. 'Filter Delegate
    9. Private Function IstReferenznummervorhanden(obj As Object) As Boolean
    10. Dim value As Materialnummern = CType(obj, Materialnummern)
    11. If Not value Is Nothing And Not value Is DBNull.Value And Not Referenznummer Is Nothing And Not Referenznummer = "" Then
    12. If value.Materialnummer.ToUpper().Contains(Referenznummer.ToUpper()) Then
    13. Return True
    14. Else
    15. Return False
    16. End If
    17. Else
    18. Return False
    19. End If
    20. End Function


    Das ganze funktioniert soweit:

    Im FIlter nutze ich die Property, die ja an die Textbox gebunden ist.
    Für mich bleibt da offen:
    1) Wie bekomme ich das in eine Klasse mit der Filterung...
    2) Wie navigiere ich schön durch die ListView (Eigentlich nur Pfeil runter/hoch und selectedindex den Value abgreifen)

    Vielleicht
    ist das mit der AutoCompleteBox auch eine schöne Lösung, wollte sie
    eben implementieren, bekomme aber einen unbekannten Buildfehler.

    Schwakowiak schrieb:

    Vorne Weg, ich habe
    eine etwas andere Lösung gefunden. Ich nutze nun eine ListCollectionView

    Was im Grund ja das ist was ich gesagt habe da eine ListcollectionView von CollectionView erbt und diese wieder ICollectionView implementiert. =O

    Schwakowiak schrieb:

    Klappt soweit ganz gut. Das ganze habe ich allerdings nicht
    über meine Klasse MaterialnummernViewModel hinbekommen, da ich nicht
    weiß, wie das mit den Filtern von statten gehen soll.

    Dafür habe ich dir einen Link zur verfügung gestellt. dort ist es wirklich ganz simpel beschrieben, ansonsten schreib doch wo es hakt...

    Wenn du mit den Pfeiltasten durch ein Listview navigieren möchtest musst du ja nur den Focus drauf setzen!?!

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.
    Hallo Sascha,
    habe es jetzt hinbekommen. Das ViewModel binde ich an eine Obersvable Collection beim Programmaufruf und diese dann im XAML an meine ListView.
    Klappt jetzt einwandfrei, dass mit navigieren habe ich einwenig anders gelöst, da die Navigation in der "TextBox" stattfinden soll. Ich greife dazu einfach auf den Selectedindex der ListView zu.

    Was mir unklar war, wie ich den Filter für den Delegate übergeben kann, habe mir das aber oben schon selbst beantworetet, beim Aufruf der PropertyChanged Funktion.
    In der übergebe ich dem ViewModel einfach meine Eingabe.

    Das schöne ist, ich kann das ViewModel mit ein paar Zeilen in vielen anderen Programmen verwenden.
    Danke !