Autor |
Beitrag |
UGrohne
Beiträge: 5502
Erhaltene Danke: 220
Windows 8 , Server 2012
D7 Pro, VS.NET 2012 (C#)
|
Verfasst: Fr 27.02.09 12:42
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
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Fr 27.02.09 15:24
Interessantes Problem, mal wieder .
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.
|
.
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 ? 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
Beiträge: 5502
Erhaltene Danke: 220
Windows 8 , Server 2012
D7 Pro, VS.NET 2012 (C#)
|
Verfasst: Fr 27.02.09 16:00
War ja klar, dass Du darauf antwortest
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
Beiträge: 5502
Erhaltene Danke: 220
Windows 8 , Server 2012
D7 Pro, VS.NET 2012 (C#)
|
Verfasst: Fr 27.02.09 17: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
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Fr 27.02.09 18:00
|
|
UGrohne
Beiträge: 5502
Erhaltene Danke: 220
Windows 8 , Server 2012
D7 Pro, VS.NET 2012 (C#)
|
Verfasst: Fr 27.02.09 22: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 . |
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 .
Kha hat folgendes geschrieben : | 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 : www.codeproject.com/...tachedBehaviors.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> | |
Das werd ich mal ausprobieren, danke
//EDIT: Funktioniert einwandfrei. Werde ich noch etwas verbessern, um weitere Funktionen, aber sieht schon sehr gut aus
|
|
|