It looks like my original answer was due to a misunderstanding of the question, and the requirement isn't about the data template selector, but rather how to parameterize the property a binding binds to, so you can use the same template for two different properties.
Quick answer: That's not the way XAML is designed to be used. You can't parameterize the Path
property of a Binding
. The conventional solution is to write one template for each case. It would be nice if you could specify which property/field a DataGridTemplateColumn
is meant to display, via a Binding
or DisplayMemberPath
property, and then passed that value to the template -- but it doesn't work that way.
I found a likely-looking workaround here, but I'm not sure the ROI on it would stack up well relative to copying and pasting a DataTemplate
and getting on with your life.
If the templates are complicated enough for maintenance to be a concern, you can work around that like so:
XAML resources:
<DataTemplate x:Key="RedBaseTemplate">
<Border BorderBrush="Green" BorderThickness="2" Margin="1">
<Label x:Name="Text" Background="Red" Content="{Binding}" />
</Border>
</DataTemplate>
<DataTemplate x:Key="GreenBaseTemplate">
<Border BorderBrush="Red" BorderThickness="2" Margin="1">
<Label x:Name="Text" Background="Green" Content="{Binding}" />
</Border>
</DataTemplate>
<DataTemplate x:Key="RedTemplateA">
<ContentControl
Content="{Binding A}"
ContentTemplate="{StaticResource RedBaseTemplate}"
/>
</DataTemplate>
<DataTemplate x:Key="RedTemplateB">
<ContentControl
Content="{Binding B}"
ContentTemplate="{StaticResource RedBaseTemplate}"
/>
</DataTemplate>
<DataTemplate x:Key="GreenTemplateA">
<ContentControl
Content="{Binding A}"
ContentTemplate="{StaticResource GreenBaseTemplate}"
/>
</DataTemplate>
<DataTemplate x:Key="GreenTemplateB">
<ContentControl
Content="{Binding B}"
ContentTemplate="{StaticResource GreenBaseTemplate}"
/>
</DataTemplate>
Original Answer
This is a common pattern: You want multiple instances of the same DataTemplateSelector
(or value converter, quite often), but with different parameters. The solution is to derive from MarkupExtension
, so you can instantiate the thing at the point of use with its own unique parameters, rather than creating one shared instance someplace else as a resource. In this case DataTemplateSelector
is a class rather than an interface, so you can't derive your selector from MarkupExtension
. Instead you write a quick MarkupExtension
that returns your selector.
I wanted to pass the templates themselves to RedGreenTemplateSelectorExtension
using StaticResource
or DynamicResource
in the XAML, but the XAML parser didn't like the idea. But this works well enough.
public class RedGreenTemplateSelectorExtension : MarkupExtension
{
public Object RedTemplateKey { get; set; }
public Object GreenTemplateKey { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider)
{
var redTemplate = new StaticResourceExtension(RedTemplateKey)
.ProvideValue(serviceProvider) as DataTemplate;
var greenTemplate = new StaticResourceExtension(GreenTemplateKey)
.ProvideValue(serviceProvider) as DataTemplate;
return new RedGreenTemplateSelector() {
RedTemplate = redTemplate,
GreenTemplate = greenTemplate
};
}
}
public class RedGreenTemplateSelector : DataTemplateSelector
{
public DataTemplate RedTemplate { get; set; }
public DataTemplate GreenTemplate { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (item is RedItem)
return RedTemplate;
else if (item is GreenItem)
return GreenTemplate;
else
return base.SelectTemplate(item, container);
}
}
XAML
<StackPanel>
<ContentControl
ContentTemplateSelector="{local:RedGreenTemplateSelector RedTemplateKey=RedTemplate, GreenTemplateKey=GreenTemplate}"
>
<local:RedItem/>
</ContentControl>
<ContentControl
ContentTemplateSelector="{local:RedGreenTemplateSelector RedTemplateKey=RedTemplate, GreenTemplateKey=GreenTemplate}"
>
<local:GreenItem/>
</ContentControl>
</StackPanel>
P.S. StaticResource
and Binding
are two very different classes that do very different things. People misuse "binding" to mean "assignment". It's not. You aren't using any bindings at all here.