| Autor |
Beitrag |
zappo
      
Beiträge: 40
|
Verfasst: Mo 26.10.09 13:07
Folgendes Problem.
Ich lese Daten aus einer XML Datei aus und speichere diese in einer ObservableCollection. Diese dient als Quelle für das Binding einer Combobox.
Nun soll es möglich sein diese Combobox zu filtern. D.h. ich habe nochmals 3 Kriterien nach denen ich die Daten in der Combobox weiter einschränken können möchte. Die eleganteste Möglichkeit wäre es nun wohl, den bereits in der ObservableCollection vorhandenen kompletten Datensatz zu filtern. Nur weiß ich nicht wie ich es anfangen soll.  Kann mir jemand einen Tipp geben?
Alternative wäre die Datenquelle bei jeder Auswahl eines Kriteriums neu abzufragen (LINQ to XML), Problem dabei ist die Verzweigung der Abfragen, hier müsste ich in der Lage sein die query dynamisch zusammenzusetzen, je nach dem welche Kriterien ausgewählt sind und welche nicht. Sonst müsste ich ja wirklich für jeden Fall eine query schreiben, das geht ja nicht...
Vielleicht weiß einer von euch zu einem der beiden Wege etwas zu sagen?
Gruß
Sebastian Moderiert von Kha: Topic aus C# - Die Sprache verschoben am Mo 26.10.2009 um 19:53
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Mo 26.10.09 20:52
Hört sich nach einem Fall für CollectionView an  :
| Zitat: | | You can think of a collection view as a layer on top of a binding source collection that allows you to navigate and display the collection based on sort, filter, and group queries, all without having to manipulate the underlying source collection itself. If the source collection implements the INotifyCollectionChanged interface, the changes that raise the CollectionChanged event are propagated to the views. |
PS: ObservableCollection rückt mit 4.0 in die BCL auf, besagte Klasse allerdings nicht, also verschiebe ich mal  .
_________________ >λ=
|
|
zappo 
      
Beiträge: 40
|
Verfasst: Mi 28.10.09 13:04
Huh.. du hast echt auf alles eine Antwort... vielen Dank noch einmal..
Das ganze wäre wohl meine Lösung.. wenn ..
Ich erkläre mal kurz wo das Problem liegt..
Ich habe eine ObservableCollection<string> welche Produktnamen beherbegt, und nur diese.
Diese dient als ItemsSource für eine Combobox.
Nun habe ich mehrere zusätzliche Comboboxen mit Parametern zum einschränken der Auswahl (Technologie, Preisgruppe...)
Das Problem daran die Collectionview zu filtern liegt also darin, das ich die Filterparamter gar nicht in der ObservableCollection drin habe ...
Nun hatte ich schon dran gedacht einfach eine ObservableCollectiony<string[]> draus zu machen, das aber stellt mich dann vor das Problem das ich die Combobox ja nicht an ein bestimmtes Element im Array binden kann wenn dieser in einer ObservableCollection steckt...
Nun denke ich mein Lösungsansatz ist schon falsch...
kannst Du, oder kann irgendjemand anders, mir einen Denkanstoss geben wie das am besten zu lösen wäre?
Wenns hilft poste ich auch nochmal nen Screenshot von der GUI an der stelle, aber ich denke es wird klar wo der Hase im Pfeffer liegt..
Gruß
Sebastian
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Mi 28.10.09 13:49
Die ObservableCollection sollte weder einen einzelnen String noch ein Array enthalten, sondern eine Entity - eine Klasse eben mit Properties wie Produktname, Preisklasse etc... Kurz gesagt, WPF erwartet von dir ein sauberes OOP-Design, nur dann läuft alles reibungslos  .
PS: Nichtsdestotrotz ist es auch in XAML möglich, ein Array zu indizieren. Ich habe gerade nur kein VS/Kaxaml zu Hand und kann nicht ausprobieren, ob schon {Binding [0]} funktioniert oder ob davor unbedingt ein Property-Name stehen muss.
_________________ >λ=
|
|
zappo 
      
Beiträge: 40
|
Verfasst: Mi 28.10.09 14:02
Kha hat folgendes geschrieben : | Die ObservableCollection sollte weder einen einzelnen String noch ein Array enthalten, sondern eine Entity - eine Klasse eben mit Properties wie Produktname, Preisklasse etc... Kurz gesagt, WPF erwartet von dir ein sauberes OOP-Design, nur dann läuft alles reibungslos .
|
Gut.. dann wäre es wohl im Sinne des Erfinders, wenn ich die ObservableCollections so oder so einfach gegen Arrays austausche welche INotifyPropertyChanged implementiere... wenn ich bei "nur Produktname" bleiben möchte.
Oder ich lege die besagte Datenstruktur dahinter, belasse es bei den ObservableCollections (was ja im Grunde sauberer wäre, und mein Problem ist ja im Grunde die Datenarmut in der Collection)... aber .. wie binde ich dann nur ein Element der Entity die dahinter liegt?
Das ist dann noch so der einzige Knackpunkt... wie mache ich das dann im ItemsSource?
Also meine Datenstruktur dahinter würde ja beinhalten - Prod.Name, Artikelno, Preis, Technologie,.... -
Wie schaffe ich es dann die Combobox so zu binden an die Collection das Prod.Name + ArtNr zusammen angezeigt werden...(zur not ginge eine zusätzliche Eigenschaft "DisplayString" welche ich derart zusammensetze, aber dann bleibt noch immer.. wie binde ich an eine einzelne eigenschaft innerhalb der entity im observablecollection?)
sry... falsch ich mich blöd anstell....
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Mi 28.10.09 19:09
zappo hat folgendes geschrieben : | | Das ist dann noch so der einzige Knackpunkt... wie mache ich das dann im ItemsSource? |
Ah, ok. Hab mir beim Tippen der letzten Antwort schon überlegt, ob das die eigentliche Frage war, dachte aber, es ginge erstmal nur um das Binden des Arrays.
Der Witz ist ja, dass du ItemsSource eigentlich beibehalten willst (denke ich  ) - SelectedItem[*] etc. soll ja immer noch die gesamte Entity zurückgeben. Allein die Anzeige soll doch geändert werden - also nehmen wir ein DataTemplate:
XML-Daten 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| <ListBox ItemsSource="{Binding Articles}"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding ArticleNo}" /> <TextBlock Text="{Binding ArticelName}" /> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> |
[*]Wobei man diese ganzen Eigenschaften in einer MVVM-Anwendung sowieso nicht braucht  .
_________________ >λ=
Zuletzt bearbeitet von Kha am Mi 28.10.09 19:53, insgesamt 1-mal bearbeitet
|
|
zappo 
      
Beiträge: 40
|
Verfasst: Mi 28.10.09 19:22
was dann wieder 2 Probleme mit sich bringt...
Ich bin an der Stelle beschränkt auf Comboboxen, der Optik wegen, diese habe ich ja gebunden an eine weitere collection als DataContext um das Selected Item weiterverwerten zu können...
Nutzte ich jetzt ein DataTemplate, werden auch alle angezeigten Dinge weitergereicht, sehe ich das richtig?
Hm... ich denke.. ich erstelle in der Tat noch eine neue Eigenschaft "DisplayName" welche ich dann weiter so behandle wie vorher.. und nutze das DataTemplate ums korrekt zu binden an die ComboBox... wird wohl das "einfachste" an dieser Stelle sein..
Ist dem etwas entgegenzusetzen das diese Vorgehensweise quasi "verbieten" würde??
Gruß
(Ich habe in der Tat das Gefühl, du bist der einzige in diesem Forum der antwortet  )
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Mi 28.10.09 20:01
zappo hat folgendes geschrieben : | Ich bin an der Stelle beschränkt auf Comboboxen, der Optik wegen, diese habe ich ja gebunden an eine weitere collection als DataContext um das Selected Item weiterverwerten zu können...
Nutzte ich jetzt ein DataTemplate, werden auch alle angezeigten Dinge weitergereicht, sehe ich das richtig? |
Das habe ich jetzt leider überhaupt nicht verstanden  . Ich habe gerade gemerkt, dass in meinem letzten Posting die Fußnote fehlte - der Hinweis, dass es (auf die eine oder andere Weise) immer ohne jegliche Control-Control-Bindings geht. Beschreibe doch mal was wo wie gebunden ist.
Zum konkreten Fall (geraten ^^): Wenn du mehrere Controls an die gleiche Collection bindest, teilen sich diese automatisch eine Standard-ICollectionView-Instanz. Das aktuelle Item ist also bei allen synchron, obwohl ObservableCollection so etwas ja gar nicht anbietet.
Zur Frage: Wie gerade beschrieben, wird über ItemsSource (ob mit oder ohne DataTemplate) die komplette Entity weitergegeben (und nur so ist es richtig). Also ja, auch die angezeigten Properties davon  .
zappo hat folgendes geschrieben : | (Ich habe in der Tat das Gefühl, du bist der einzige in diesem Forum der antwortet ) |
Dass ich in der WPF-Sparte überdurchschnittlich vertreten bin, will ich nicht leugnen, was aber auch darauf hindeutet, dass es doch eher ein Spezialthema ist - und zufällig eben eines meiner absoluten Lieblingsthemen  .
_________________ >λ=
|
|
zappo 
      
Beiträge: 40
|
Verfasst: Mi 28.10.09 20:39
Dann hoffe ich in der Tat dich nicht schon zu nerven..
Also ganz konkret,
ich habe eine ComboBox, diese binde ich via ItemsSource an eine ObservableCollection.
Selbige Combobox binde ich via DataContext an eine andere ObservableCollection um auf Änderungen zu reagieren.
Nun muss eben quasi gefiltert werden das in der Combobox drin steht, das soll geschehen durch Suchparameter welche in 3 anderen Comboboxen sitzen.
(Gerade wird mir bewusst, das ich eigentlich auf die ObservableCollections verzichten könnte... :-/ )
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Mi 28.10.09 21:25
zappo hat folgendes geschrieben : | ich habe eine ComboBox, diese binde ich via ItemsSource an eine ObservableCollection.
Selbige Combobox binde ich via DataContext an eine andere ObservableCollection um auf Änderungen zu reagieren. |
Das Setzen von DataContext hat auf Controls keinen Einfluss. ItemsControls lassen sich nur mit genau einer Collection verbinden, eben über ItemsSource (oder Items). Was genau hast du denn mit deinen zwei Collections vor  ?
zappo hat folgendes geschrieben : | | Nun muss eben quasi gefiltert werden das in der Combobox drin steht, das soll geschehen durch Suchparameter welche in 3 anderen Comboboxen sitzen. |
Ok, das sollte über die Filter-Property von CollectionView funktionieren. Wenn du aber auf die ObservableCollections anscheinend verzichten kannst, kannst du im ViewModel auch einfach eine IEnumerable-Property nehmen, die mit .Where filtern und natürlich immer schön PropertyChanged feuern  . Dazu könnte ich bei Bedarf auch ein kurzes Beispiel posten.
_________________ >λ=
|
|
zappo 
      
Beiträge: 40
|
Verfasst: Mi 28.10.09 21:39
| Zitat: | Das Setzen von DataContext hat auf Controls keinen Einfluss. ItemsControls lassen sich nur mit genau einer Collection verbinden, eben über ItemsSource (oder Items). Was genau hast du denn mit deinen zwei Collections vor ? |
Naja... in der einen List liegen meine ELemente welche angezeigt werden, in der anderen wird jeweils das SelectedItem abgelegt damit ich drauf reagieren kann?? Krasser Denkfehler?? Funktionieren tut es.. nur stosse ich jetzt beim Filtern eben auf Grenzen...
| Zitat: | Ok, das sollte über die Filter-Property von CollectionView funktionieren. Wenn du aber auf die ObservableCollections anscheinend verzichten kannst, kannst du im ViewModel auch einfach eine IEnumerable-Property nehmen, die mit .Where filtern und natürlich immer schön PropertyChanged feuern . Dazu könnte ich bei Bedarf auch ein kurzes Beispiel posten. |
Das hört sich ja klasse an..
Ja ... also ein Beispiel wär natürlich die absolute Oberklasse... :-O
Haken an der Sache ist dann ja noch das die 3 Kriterien zum filtern unabhängig voneinander laufen müssen.. hatte auch schon drüber nachgedacht ne ArrayList zu nehmen welche ich dann eben einmal kopiere um den "ungefilterten Ausgangszustand" jederzeit noch zu haben, und dann die andere ArrayList je nach gesetzten FIltern immer wieder neu fülle... Ist nur das Problem das die ArrayList ein automatisches reagieren der Combobox auf Änderungen nicht wirklich schöner macht.... einfach INotifyPropertyChanged reicht da nicht.. da muss man schon das ItemsSource jedesmal neu setzen...
GrußGruß
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Mi 28.10.09 22:01
Zuletzt bearbeitet von Kha am Mi 28.10.09 22:09, insgesamt 2-mal bearbeitet
|
|
zappo 
      
Beiträge: 40
|
Verfasst: Mi 28.10.09 22:06
| Zitat: | | Du willst erstmal nichts von meinen Observable<T>s sehen |
Das kann man so wirklich nicht sagen..... ich finde das schon wirklich cool.. nur das hier muss jetzt einfach erstmal nur fertig werden,... danach.. beschäftige ich mich mal wieder mit sachen die ich auch interessant finde.. wozu dann auch deine Observable<T>s gehören! 
|
|
zappo 
      
Beiträge: 40
|
Verfasst: So 01.11.09 14:23
Die Rückmeldung hier möchte ich auf keinen Fall schuldig bleiben.
Für alle, die ähnliche Probleme haben, Kha's Lösung funktioniert unter den beschriebenen Bedingungen hervorragend!
Ändert sich die Datenbasis, sollte das auch zu machen sein in dem man eben alles neu initialisiert...
nicht schön.. aber sollte hinhauen.
Gruß
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: So 01.11.09 16:18
Schön zu hören  .
zappo hat folgendes geschrieben : | Ändert sich die Datenbasis, sollte das auch zu machen sein in dem man eben alles neu initialisiert...
nicht schön.. aber sollte hinhauen. |
Ich behaupte einfach mal "das geht sicher auch anders!", auch wenn ich keinen Plan habe, worum es geht  .
_________________ >λ=
|
|
|