Entwickler-Ecke
WPF / Silverlight - ListView: GridViewColumns dynamisch binden
UGrohne - Fr 27.02.09 11:42
Titel: ListView: GridViewColumns dynamisch binden
Hallo,
ich schreibe gerade eine Applikation im MVVM-Pattern, in der mehrere Listen angezeigt werden sollen. Dazu möchte ich die Verwaltung der Listenansichten gerne in einer Basisklasse zentralisieren, vor allem um später die Wiederverwendbarkeit beispielsweise für Suchdialog zu gewährleisten. Problem ist nun, dass jede spezialisierte Liste über eigene Spalten verfügt, die angezeigt werden sollen, daher muss ich diese Spalten dynamisch aufbauen. Ich möchte aber nach dem Prinzip des MVVM keine direkte Verknüpfung zwischen XAML-View und der ModelView-Klasse haben, daher das gerne über DataBinding lösen. Außerdem kann ich darüber dann sehr einfach Sortier-, Gruppier- und Filterfunktionen bereitstellen.
Und nun das Problem: Ich dachte mir, ich könnte mir einfach eine List<GridViewColumn> bauen, die mir die anzuzeigenden Spalten enthält und binde diese per {Binding} an den Content des GridView-Elements innerhalb der Listview.
Doch dummerweise kann ich weder im Content, noch in der ColumnCollectionProperty des GridView ein Binding einbauen. Wie kann ich das Problem jetzt lösen?
Grüße,
Uwe
Kha - Fr 27.02.09 14:24
Interessantes Problem, mal wieder :D .
Es gibt zwar eine Attached Property ColumnCollection aber...
| Zitat: |
Do not use this method to change the columns collection for a GridView object. To get, set, or change the columns that are defined for a GridView object, use the Columns property.
|
:mrgreen: .
Also musst du doch über Columns.Add gehen, am einfachsten wahrscheinlich im Code-Behind. Für Dynamisches wäre das DataGrid aus dem WPF-Toolkit wohl eher geeignet ;) .
Aber ich frage mich gerade: Gehören GridViewColumns denn in das View Model? Ich würde dann doch für jede Datenquelle ein passendes GridView in den Ressourcen festlegen. Fragt sich nur noch, wie du das passende dann der (dem :gruebel: ? Argh) ListView zuordnest. Dafür könntest du im VM eine Property
Type ItemType festlegen und diese in einem Style für die ListView über Data Trigger auswerten, also etwa:
XML-Daten
1: 2: 3:
| <Style.Triggers> <DataTrigger Binding="{Binding ItemType}" Value="{x:Type ItemA}"> <Setter Property="View" Value="{StaticResource GridViewForItemA}" /> |
UGrohne - Fr 27.02.09 15:00
War ja klar, dass Du darauf antwortest :P
Die CodeBehinds will ich überhaupt nicht nutzen ;).
Ja, das ins VM wieder unterzubringen ist evtl. nicht ganz sauber, aber ich will die Möglichkeit haben, allgemein das zu bestimmen, was angezeigt werden soll, aber dem Benutzer auch die Möglichkeiten bieten (später) weitere Spalten hinzufügen zu können.
Und gerade für ein Suchwindow, das dann alle ListViewModels (dafür habe ich so eine Basisklasse erstellt, die schon eine generische ObservableCollection bereitstellt, die von den Nachfahren nur noch gefüllt werden muss) unterstützt, wäre das natürlich genial.
Ist das DataGrid denn inzwishcen final? Ich hab mir das noch nie angeschaut.
Vielleicht komme ich heute Abend nochmal dazu, mir das anzuschauen.
UGrohne - Fr 27.02.09 16:23
Hab mir eben schnell das DataGrid angeschaut, das bringt mir in der Hinsicht noch weniger, weil die Columns-Collection gar nicht das DependencyProperty, sondern als ObservableCollection implementiert ist.
Oder hattest Du da an ein anderes Vorgehen gedacht? Ich will jedenfalls auf keinen Fall direkt auf das Grid zugreifen müssen. Unter Umständen muss ich ansonsten eben ein eigenes Control vom GridView ableiten und diese Collection als DependencyProperty implementieren.
Kha - Fr 27.02.09 17:00
UGrohne hat folgendes geschrieben : |
| Ist das DataGrid denn inzwishcen final? Ich hab mir das noch nie angeschaut. |
In Entwicklung ist es noch, aber die erste Version heist zumindest nicht mehr "Beta".
UGrohne hat folgendes geschrieben : |
| Oder hattest Du da an ein anderes Vorgehen gedacht? |
Ich dachte da eher so an AutoGenerateColumns :mrgreen: .
UGrohne hat folgendes geschrieben : |
| Ich will jedenfalls auf keinen Fall direkt auf das Grid zugreifen müssen. Unter Umständen muss ich ansonsten eben ein eigenes Control vom GridView ableiten und diese Collection als DependencyProperty implementieren. |
Ableiten ist bei WPF meistens unnötig ;) :
http://www.codeproject.com/KB/WPF/AttachedBehaviors.aspx
In etwas so:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22:
| public static class GridViewHelper { public static readonly DependencyProperty ColumnBindingPathsProperty = DependencyProperty.RegisterAttached("ColumnBindingPaths", typeof(IEnumerable<string>), typeof(GridViewHelper), new UIPropertyMetadata( (d, e) => { GridView view = (GridView)d; view.Columns.Clear(); foreach (string path in (IEnumerable<string>)e.NewValue) view.Columns.Add(new GridViewColumn { DisplayMemberBinding = new Binding(path), Header = path }); } ));
public static IEnumerable<string> GetColumnBindingPaths(DependencyObject obj) { return (IEnumerable<string>)obj.GetValue(ColumnBindingPathsProperty); }
public static void SetColumnBindingPaths(DependencyObject obj, IEnumerable<string> value) { obj.SetValue(ColumnBindingPathsProperty, value); } } |
XML-Daten
1: 2: 3:
| <ListView.View> <GridView my:GridViewHelper.ColumnBindingPaths="{Binding ColumnPaths}" /> </ListView.View> |
UGrohne - Fr 27.02.09 21:29
Kha hat folgendes geschrieben : |
UGrohne hat folgendes geschrieben : | | Oder hattest Du da an ein anderes Vorgehen gedacht? | Ich dachte da eher so an AutoGenerateColumns :mrgreen: . |
Das bringt mir aber nichts, weil ich ja nicht alle Inhalte zeigen will und ich außerdem mit Objekten arbeite. Wenn da alles angezeigt wird, dann brauch ich zwei 24"-Monitore nebeneinander ;).
Das werd ich mal ausprobieren, danke :)
//EDIT: Funktioniert einwandfrei. Werde ich noch etwas verbessern, um weitere Funktionen, aber sieht schon sehr gut aus :)
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!