views:

95

answers:

2

I have 8 different XAML DataTemplates that are all very similar. Here are 2 of them:

<DataTemplate x:Key="ConflictFieldStringCellContentTemplate">
    <StackPanel>
        <TextBlock Text="{Binding ClientVersion.Value}"
                   Foreground="{Binding Path=Mismatch, Converter={StaticResource mismatchBoolToBrushConverter}}" />
        <Label Background="LightGray" Height="1" Margin="0, 4, -4, 2"></Label>
        <TextBlock Text="{Binding ServerVersion.Value}"
                   Foreground="{Binding Path=Mismatch, Converter={StaticResource mismatchBoolToBrushConverter}}"/>
    </StackPanel>
</DataTemplate>

<DataTemplate x:Key="ConflictFieldStringArrayCellContentTemplate">
    <StackPanel>
        <TextBlock Text="{Binding ClientVersion.Value, Converter={StaticResource stringArrayToCommaDelimitedStringConverter}}"
                   Foreground="{Binding Path=Mismatch, Converter={StaticResource mismatchBoolToBrushConverter}}"/>
        <Label Background="LightGray" Height="1" Margin="0, 4, -4, 2"></Label>
        <TextBlock Text="{Binding ServerVersion.Value, Converter={StaticResource stringArrayToCommaDelimitedStringConverter}}"
                   Foreground="{Binding Path=Mismatch, Converter={StaticResource mismatchBoolToBrushConverter}}"/>
    </StackPanel>
</DataTemplate>

As you can see, the only difference is that they use a different Converter for the Binding of the Text property of the TextBlock. Is there any way for me to factor out the commonalities of these two DataTemplates? I have 6 more and updating them is getting very tedious, because everything is identical except for the Converter for the Binding of the Text property.

Is there a way to somehow factor this out into one template which can be parameterized somehow? Something like this would be cool (pseudo-code):

<DataTemplate x:Key="BaseCellContentTemplate">
    <StackPanel>
        <TextBlock Text="{??}"
                   Foreground="{Binding Path=Mismatch, Converter={StaticResource mismatchBoolToBrushConverter}}" />
        <Label Background="LightGray" Height="1" Margin="0, 4, -4, 2"></Label>
        <TextBlock Text="{Binding ServerVersion.Value}"
                   Foreground="{Binding Path=Mismatch, Converter={StaticResource mismatchBoolToBrushConverter}}"/>
    </StackPanel>
</DataTemplate>

<DataTemplate x:Key="ConflictFieldStringCellContentTemplate" BaseTemplate="BaseCellContentTemplate">
    <??>{Binding ClientVersion.Value}</??>
</DataTemplate>

<DataTemplate x:Key="ConflictFieldStringArrayCellContentTemplate" BaseTemplate="BaseCellContentTemplate">

    <??>{Binding ClientVersion.Value, Converter={StaticResource stringArrayToCommaDelimitedStringConverter}}</??>
</DataTemplate>
+2  A: 

One path you can try is to create a new User Control.

This User Control should contain the StackPanel, and this StackPanel should contain the TextBox, Label and TextBox.

You could implement the TextConverters as dependency properties.

The final set of DataTemplates would look like this:

    <DataTemplate x:Key="ConflictFieldStringCellContentTemplate">    
       <local:VersionDisplayControl 
                  ClientVersionTextConverter="{StaticResource stringArrayToCommaDelimitedStringConverter}" />
    </DataTemplate>

   <DataTemplate x:Key="ConflictFieldStringArrayCellContentTemplate">
       <local:VersionDisplayControl 
          ClientVersionTextConverter="{StaticResource stringArrayToCommaDelimitedStringConverter}"
          ServerVersionTextConverter="{StaticResource stringArrayToCommaDelimitedStringConverter}" />
    </DataTemplate>

This is assuming that the User Control is able to access the source version information from some globally available source. If not, the VersionDisplayControl will have to expose another public property, probably called VersionSource.

Andrew Shepherd
+1  A: 

If there is only one value, and you want to do it purely with templates, you might do:

<DataTemplate x:Key="VersionDisplayTemplate">
    <StackPanel>
        <TextBlock Text="{TemplateBinding Tag}"
                   Foreground="{Binding Path=Mismatch, Converter={StaticResource mismatchBoolToBrushConverter}}" />
        <Label Background="LightGray" Height="1" Margin="0, 4, -4, 2"></Label>
        <TextBlock Text="{TemplateBinding Content}"
                   Foreground="{Binding Path=Mismatch, Converter={StaticResource mismatchBoolToBrushConverter}}"/>
    </StackPanel>
</DataTemplate>

Now you can use it as:

<DataTemplate x:Key="ConflictFieldStringCellContentTemplate">    
   <ContentPresenter 
       Tag="ABC"
       Content="{Binding ClientVersion.Value}" 
       ContentTemplate="{StaticResource VersionDisplayTemplate}" 
       />
</DataTemplate>

<DataTemplate x:Key="ConflictFieldStringArrayCellContentTemplate">
   <ContentPresenter 
       Tag="XYZ"
       Content="{Binding ClientVersion.Value, Converter={StaticResource stringArrayToCommaDelimitedStringConverter}}" 
       ContentTemplate="{StaticResource VersionDisplayTemplate}"
       />
</DataTemplate>
Paul Stovell