In this hypothetical example, imagine I have an object FooSet that has five properties Foo1, Foo2, Foo3 Foo4 and Foo5 all of which are type Foo which itself has several properties. Finally, I have a DataTemplate called FooTemplate that knows how to display objects of type Foo in a graphical way.
Now when using the built-in DataGrid, ItemsSource is a collection of FooSet objects. What I want to do is set up five templated columns that all use the FooTemplate data template. However, the DataGrid's template column type doesn't let me set the data source for that column (e.g. Foo1, Foo2, etc.) so I end up duplicating the template, once for each column, just changing Foo1.SomeProp to Foo2.SomeProp in the template's bindings, which is ridiculous of course. But I for the life of me can't find how to say 'Column B uses Foo2 as it's data source.'
Here's some Pseudo-XAML to show what I want...
<Resources>
<DataTemplate TargetType="Foo">
<StackPanel>
<local:FooPropAControl Value="{Binding FooPropA}" />
<local:FooPropBControl Value="{Binding FooPropB}" />
<local:FooPropCControl Value="{Binding FooPropC}" />
</StackPanel>
</DataTemplate>
</Resources>
<DataGrid ItemsSource="{Binding MyItems}" AutoGenerateColumns="false">
<DataGrid.Columns>
<DataGridTemplateColumn DataSource="{Binding Foo1}" />
<DataGridTemplateColumn DataSource="{Binding Foo2}" />
<DataGridTemplateColumn DataSource="{Binding Foo3}" />
<DataGridTemplateColumn DataSource="{Binding Foo4}" />
<DataGridTemplateColumn DataSource="{Binding Foo5}" />
</DataGrid.Columns>
</DataGrid>
Even if I have to explicitly specify the template in the column, that's still fine. It's setting the data source for that column to a property of FooSet so I can just use one DataTemplate. All the other columns let you set some binding that does that. I even tried subclassing DataGridTemplateColumn to add DataSource but didn't get too far (my guess is because there isn't a column per se but rather that dictates how cells in rows are generated, but that's just a guess.)
Now I know the 3rd-party Xceed grid lets you specify exactly that but I'm hoping for a native solution.
So, howzyadoodat? Or can you?
M
Good question, i would approach it using a
ContentControl
, the code will still be a bit inflated but it's better than duplicating the whole template, e.g.:Here i use one implicit DataTemplate in the resources but you could also apply it explicitly as the
ContentTemplate
of each ContentControl by defining & referencing a key but you know that anyway.Barebone subclassing approach:
You could use a ContentControl within each column to provide the required binding:
A ContentControl is a lookless control that renders its Content, (which defaults to its DataContext) using a template. Therefore your implicit DataTemplate should be used.
This is a cleaned-up version of something extremely similar to what @H.B. suggested. However, SO etiquette says to vote for others when you can so even though this is the one I'm using, I still voted him as accepted.
...and here's how you use it...