WPF has a lot of power and flexibility which is great but that also means there are several ways to do the same thing. That helped trip me up for a little bit this afternoon when I was trying to remember details on triggers.

I had a GridView bound to a collection of DatabaseChange POCO objects with IsAttachment and Schema properties. I simply wanted the Schema cell to be editable when IsAttachment was True and read-only otherwise. I went through a couple different variations but settled on the below.

The view’s resources contains a DataTemplate for each of the states, readonly and editable. Another DataTemplate defines a ContentPresenter and a trigger that swaps out the ContentTemplate on the presenter if the DataTrigger binding condition is satisified.

<UserControl.Resources>
    <DataTemplate x:Key="SchemaColumnEditable">
        <ComboBox IsEditable="True" 
        ItemsSource="{Binding DataContext.Schemas, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DockPanel}}" 
                  Text="{Binding Schema, Mode=TwoWay}" />            
    </DataTemplate>
    <DataTemplate x:Key="SchemaColumnReadOnly">
        <TextBlock Text="{Binding Schema, Mode=OneWay}"/>
    </DataTemplate>
            
    <DataTemplate x:Key="schemaDetails">
        <ContentPresenter x:Name="schemaContentPresenter" 
            ContentTemplate="{StaticResource SchemaColumnReadOnly}" 
            Content="{TemplateBinding Content}" />
        <DataTemplate.Triggers>
            <DataTrigger Binding="{Binding IsAttachment}" Value="True">
                <Setter TargetName="schemaContentPresenter"  Property="ContentTemplate"  
                Value="{StaticResource SchemaColumnEditable}" />
            </DataTrigger>
        </DataTemplate.Triggers>
    </DataTemplate>
</UserControl.Resources>      

Use of the template in the GridView:

<!-- ListView attributes and other GridView columns removed for brevity -->
<ListView>
    <ListView.View>
        <GridView>                                
            <GridViewColumn Header="Schema" Width="90" 
            CellTemplate="{StaticResource schemaDetails}" />                                
        </GridView>
    </ListView.View>
</ListView>

Simple enough. It’s also worth nothing to not forget to remove the DisplayMemberBinding property on the GridViewColumn when changing it to use a cell template as otherwise the template will not take effect.

This is a part of a “Database Packager” feature in a larger set of build management apps I have been working on since inheriting dreaded release engineer responsibilities from a project manager who left the company and has been sorely missed. Hopefully there will be more here on the release management front later if I can make the time…