Dynamically Specify and Modify Silverlight DataGrid Columns at Runtime (MVVM)
What's the best method for dynamically specifying DataGrid columns in a Silverlight DataGrid control at runtime following the MVVM pattern?
What I would like to do would be to bind the "DataGrid.Columns" property to a property in my ViewModel so that if the user adds / removes columns, I just update the ViewModel property and the DataGrid will change. The problem is the DataGrid.Columns property cannot be bound (I don't think so).
Since this property is not available and the DataGrid control itself is not available at the ViewModel level, my current approach is to go beyond the MVVM pattern for this particular implementation and capture specific events in Code View using the MVVM Light Messenger class, then talk directly with the DataGrid control to achieve this capability. I know this is a general statement to this approach without details, but is there an easier way ... or maybe not much simpler, but a better way that sticks to the MVVM pattern is slightly better?
It drives me crazy that the DataGrid control Columns property cannot be linked ... seems to be such a simple thing.
FYI - before suggesting to use AutoGenerateColumns = True the class is bound for every item in the collection bound to the DataGrid.ItemsSource has no individual properties to define what is bound to the columns ... this is the property of the collection which contains the columns to keep them completely dynamic to exclude a specific path. Also, processing with AutoGeneratingColumns and using e.Cancel to show / hide columns is also possible for the same reason (I think).
a source to share
I agree that this is a pain not to bind DataGrid.Columns. My recommendation here would be to define your columns in the ViewModel in an ObservableCollection. In the view (code behind), handle the CollectionChanged event of this ObservableCollection and change the DataGrid.Columns in code.
While this solution is less elegant, it is simple. For your ViewModel, you can unit test so that the CollectionChanged event is properly raised when adding, removing, or moving columns. The view code cannot be tested, so I guess this is something you need to live with. The advantage is that if the DataGrid.Columns property can be tied to the database on some day, it will be easy to refactor that to remove the code behind.
Another way (I think) would be to create a bound behavior or Blend behavior to take care of this. Attach it to the DataGrid; instead of binding to DataGrid.Columns directly, bind the property to the behavior and change the behavior of the DataGrid (AssociatedObect) directly.
It makes sense? Cheers, Laurent
a source to share