Defining and mapping DataGrid columns in WPF declaratively using bindings?

Is there a way to specify columns of a DataGrid declaratively using binding? (And set the column properties using this binding?) Idealy, I would have a list of object bindings (like rows) to ItemsSource, and one of their properties would be a dictionary (or a list of objects of a particular class or something else) with the name and value. I would like DataGrid to automatically create these additional columns without having any code. Is it possible? Or how would you get around this?

An array containing additional values ​​may change over time, but will be the same for all elements in the list.

It would be possible (and clean) to supply a DataGrid with another list so that it can create columns. But for this I will need something like ColumnsSource or something like that.

The only thing I could think of was to create a subclass of DataGrid ...

Any ideas?

EDIT: The point is to achieve this without any code ...

+3
source share
3 answers

At the risk of sounding contradictory ...

I think this is one example where View really needs a little "code boost" and the "no code-behind" manual can be inserted one way - if you remember that your problems are shared.

In the past, I dynamically created DataGrid controls by capturing the corresponding data from the ViewModel and writing the BuildDataGrid method similar to the Partial Response in the code. I believe that this is justified because this code was simply related to adding a view, and I didn’t mix the problems because it implemented business rules - it just put the columns together and, if necessary, created Bindings columns.

But if it's more important to keep the code clean, I would recommend your original thought about creating a custom control and using DP to “subclass” the control.

+1
source

In your XAML, bind your datagrid to an ObservableCollection of objects of a particular class that has properties.

XAML:

<WpfToolkit:DataGrid x:Name="MyDataGrid" ItemsSource="{Binding Path=Collection}" HorizontalScrollBarVisibility="Hidden" SelectionMode="Extended" CanUserAddRows="False" CanUserDeleteRows="False" CanUserResizeRows="False" CanUserSortColumns="False" AutoGenerateColumns="False" RowHeaderWidth="25" RowHeight="25"/> 

Then you can create your columns programmatically in C # / VBA and bind each individual column to a class property to which the ObservableCollection contains its objects. By adding class objects, you add rows to the datagrid. In other words, each class object in an ObservableCollection will be a row, and the class properties will be columns.

Here is an example of how to programmatically bind your columns ... C #:

 ObservableCollection<IData> datagridData = new ObservableCollection< IData >(); Binding items = new Binding(); PropertyPath path = new PropertyPath("Name"); // 'Name' is actually the name of the variable representing the property items.Path = path; MyDataGrid.Columns.Add(new DataGridTextColumn() { Header = "Names", Width = 275, Binding = items }); //repeat the creation of columns //... //- Add some objects to the ObservableCollection //- Then bind the ItemsSource of the datagrid to the ObservableCollection datagridData .Add(new Data("Bob", string.Empty)); MyDataGrid.DataContext = new DataModel{ MyData = datagridData }; 

* Editing: Sorry for that! Here's how you can achieve the same thing in XAML:

 <WpfToolkit:DataGrid x:Name="MyDataGrid" ItemsSource="{Binding Path=Collection}" HorizontalScrollBarVisibility="Hidden" SelectionMode="Extended" CanUserAddRows="False" CanUserDeleteRows="False" CanUserResizeRows="False" CanUserSortColumns="False" AutoGenerateColumns="False" RowHeaderWidth="25" RowHeight="25"> <WpfToolkit:DataGridTextColumn Header="Names" Width="2*" Binding="{Binding Path=Name}"/> <WpfToolkit:DataGridTextColumn Header="Names" Width="2*" Binding="{Binding Path=Age}"/> </WpfToolkit:DataGrid.Columns> </WpfToolkit:DataGrid> 

Edit 2: This is what the ObservableCollection and class code looks like in C #:

 public class DataModel { public ObservableCollection<IData> MyData{ get; set; } } public interface IData { string Name{ get; set; } string Age{ get; set; } } public class Data : IData { public Data(string name, string age) { Name= name; Age= age; } public string Name{ get; set; } public string Age{ get; set; } } 
+1
source

I think you will have to subclass the grid. Columns are not a binding property. if you cannot get attached to it, you cannot dynamically knit with it in xaml.

Regarding the use of elements to create columns, does this mean that if there were no elements in the grid, there would be no columns?

If you have a subclass of a grid that has a column property that you can bind to, then the place to dynamically change the columns will be in your view model.

0
source

All Articles