Issues related to WPF DataGridCell content in XAML

I used the following entry to implement datagrid binding to a list of dynamic objects

Linking DynamicObject to DataGrid with automatic column generation?

The ITypedList GetItemProperties method works fine, the grid is displayed with all the columns that I described.

I use my own PropertyDescriptor and override the GetValue and SetValue methods as described in the above publication, I also implement the TryGetMember and TrySetMember methods in dynamic objects.

so basically I have ComplexObject: DynamicCobject with a Dictionary field and ComplexObjectCollection implementing ITypedList and IList.

All this works fine, except when I bind the itemsSource DataGrid to the collection, the cells will show the name of the SimpleObject type, and I really want to implement a template to display the Value property for the SimpleObject in the text block.

I used all kinds of methods to try to get the base SimpleObject, but nothing works, and I always get ComplexObject for the string. I use autogenerated columns and it always seems to create a text column, this may be a problem, but why can't I get the underlying SimpleObject somewhere in the cell properties?

Below will be my perfect solution, but it will not work.

<Grid> <Grid.Resources> <DataTemplate x:Key="DefaultNodeTempate"> <ContentControl Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}"> <ContentControl.Resources> <DataTemplate DataType="local:SimpleObjectType"> <TextBlock Text="{Binding Value}" /> </DataTemplate> </ContentControl.Resources> </ContentControl> </DataTemplate> </Grid.Resources> <DataGrid ItemsSource="{Binding ElementName=mainWin, Path=DynamicObjects}"> <DataGrid.Resources> <Style TargetType="DataGridCell"> <Setter Property="ContentTemplate" Value="{StaticResource DefaultNodeTempate}" /> </Style> </DataGrid.Resources> </DataGrid> </Grid> 

Any suggestions would be highly appreciated.

thanks

Kieran

+1
source share
1 answer

So, I found that the solution was to do some work in the code.

In the AutoGeneratingColumn event, create a DataTemplate with a content control and a custom template selector (I create a selector in Xaml and found it as a resource).

Create a binding for ContentProperty ContentControl named e.PropertyName as the path

Create a new DataGridTemplateColumn and set the new CellTemplate columns to the new DataTemplate

replace e.Column with your new column and suppose the datacontext cells are bound to the dynamic property for this column.

If anyone has any refinement, please feel free to share your thoughts.

thanks

EDIT: as requested by the code for my solution

Custom template selector:

 public class CustomDataTemplateSelector : DataTemplateSelector { public List<DataTemplate> Templates { get; set; } public CustomDataTemplateSelector() : base() { this.Templates = new List<DataTemplate>(); } public override DataTemplate SelectTemplate(object item, DependencyObject container) { DataTemplate template = null; if (item != null) { template = this.Templates.FirstOrDefault(t => t.DataType is Type ? (t.DataType as Type) == item.GetType() : t.DataType.ToString() == item.GetType().ToString()); } if (template == null) { template = base.SelectTemplate(item, container); } return template; } } 

XAML:

 <Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfApplication1" Title="MainWindow" Height="350" Width="525"> <Grid x:Name="ParentControl"> <Grid.Resources> <local:CustomDataTemplateSelector x:Key="MyTemplateSelector" > <local:CustomDataTemplateSelector.Templates> <DataTemplate DataType="{x:Type local:MyCellObject}" > <TextBox Text="{Binding MyStringValue}" IsReadOnly="{Binding IsReadOnly}" /> </DataTemplate> </local:CustomDataTemplateSelector.Templates> </local:CustomDataTemplateSelector> </Grid.Resources> <DataGrid ItemsSource="{Binding Rows}" AutoGenerateColumns="True" AutoGeneratingColumn="DataGrid_AutoGeneratingColumn" > </DataGrid> </Grid> </Window> 

Code behind:

 private void DataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e) { // Get template selector CustomDataTemplateSelector selector = ParentControl.FindResource("MyTemplateSelector") as CustomDataTemplateSelector; // Create wrapping content control FrameworkElementFactory view = new FrameworkElementFactory(typeof(ContentControl)); // set template selector view.SetValue(ContentControl.ContentTemplateSelectorProperty, selector); // bind to the property name view.SetBinding(ContentControl.ContentProperty, new Binding(e.PropertyName)); // create the datatemplate DataTemplate template = new DataTemplate { VisualTree = view }; // create the new column DataGridTemplateColumn newColumn = new DataGridTemplateColumn { CellTemplate = template }; // set the columns and hey presto we have bound data e.Column = newColumn; } 

Perhaps there is a better way to create a data template that I recently read that Microsoft suggests using XamlReader, but then I did. Also I have not tested this on a dynamic class, but I am sure that it should work anyway.

0
source

All Articles