By default all table columns are auto-generated using 4 predefined templates (Text, Hyperlink, CheckBox, and ComboBox) that support read-only and edit modes. If you wish to customize the way some columns are rendered you can also define a custom template and assign it to some columns by hooking into the AutoGeneratingColumns
event of the DataGrid as described here.
Problem with generic columns
As you can see creating custom templates for columns is pretty straightforward as long as column names are fixed. If your WPF app uses a table that doesn't change dynamically you are all good. The problem starts when you use your datagrid to display tables, whose columns` names change e.g. tables loaded from a file at runtime. This is because you can't use the column name in your custom template.Solution 1 - Create template programmatically
In this solution you build your custom template in code and assign it to the chosen column at runtime, in theAutoGeneratingColoumn
event handler.
private void DataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e) { // First get the corresponding DataColumn var colName = e.PropertyName; var table this.DataContext as DataTable; var tableColumn = table.Columns[colName]; // choose columns to customize e.g. by type if (YOUR CONDITION E.G. COLUMN TYPE) { var templateColumn = new DataGridTemplateColumn(); templateColumn.Header = colName; templateColumn.CellTemplate = this.BuildCustomCellTemplate(colName); templateColumn.SortMemberPath = colName; e.Column = templateColumn; } } // builds custom template private DataTemplate BuildCustomCellTemplate(string columnName) { var template = new DataTemplate(); var button = new FrameworkElementFactory(typeof (Button)); template.VisualTree = button; var binding = new Binding(); binding.Path = new PropertyPath(columnName); button.SetValue(ContentProperty, binding); return template; }The code above would create the following template for selected columns:
Obviously this is just an example - in real life you would need more than just a button that does nothing. In your code you can define full templates, use binding converters, assign commands etc. However, the code gets pretty complex. Therefore this solution is suitable for simple templates.
Solution 2 - Create template skeleton
Alternatively, you can create the template skeleton in XAML and replace all bindings in your event handler:And the event handler:
private void DataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e) { (...) if (YOUR CONDITION E.G. COLUMN TYPE) { // Create wrapping template in code and populate all bindings accordingly string xaml = @"The advantage of this approach is that you can create more complex templates in XAML and in your event handler code only populate all required bindings. The limitation of this method is that the custom template needs to be defined at the application level. I found this solution here."; var template = (DataTemplate)XamlReader.Load(string.Format(xaml, "{Binding " + colName + "}", "{StaticResource customCellTemplate}")); templateColumn.CellTemplate = template; (...) } }
No comments:
Post a Comment