4

I'm putting together some generic CellTemplate styles for a WPF grid (WPFToolKit DataGrid), and I’m not sure of the syntax to use to make the binding generic. So for example, I have this template, which turns the value red if the value is negative:

<DataTemplate x:Key="RedNegativeCellTemplate">
    <TextBlock Name="QuantityTextBox" Text="{Binding Quantity, StringFormat='c', Mode=OneWay}"/>
    <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding Quantity, Converter={StaticResource SignConverter}}" Value="-1">
            <Setter TargetName="QuantityTextBox" Property="Foreground" Value="Red"/>
        </DataTrigger>
    </DataTemplate.Triggers>
</DataTemplate>

You’ll notice that this has a binding on the Text box to the column value ‘Quantity’ - i.e., the field/column that the binding comes from is explicit.

So I can use this in my WPF DataGrid as follows:

<sdk:DataGrid ItemsSource="{Binding MyDataSource}" AutoGenerateColumns="False">
    <sdk:DataGrid.Columns>

        <sdk:DataGridTemplateColumn Header="Net Quantity" CellTemplate="{StaticResource RedNegativeCellTemplate}"/>

    </sdk:DataGrid.Columns>
</sdk:DataGrid>

But… what I’d really like to do is to have the field binding generic for the template, so that I can re-use the template as follows:

<sdk:DataGrid ItemsSource="{Binding OrdersQuery}"AutoGenerateColumns="False">
    <sdk:DataGrid.Columns>
        <sdk:DataGridTemplateColumn Header="Quantity" CellTemplate="{StaticResource RedNegativeCellTemplate}"/>
        <sdk:DataGridTemplateColumn Header="Price" CellTemplate="{StaticResource RedNegativeCellTemplate}"/>
        <sdk:DataGridTemplateColumn Header="Total" CellTemplate="{StaticResource RedNegativeCellTemplate}"/>
    </sdk:DataGrid.Columns>
</sdk:DataGrid>

Now, the problem here is that there doesn't seem to be a way to parameterize the binding in the CellTemplate. But I'm loath to have to have 3+ lines of controltemplate for every column that uses this template, as it clutters the XAML and makes it far less readable (not to mention the fact that if I decide to change the cell template to put a border around the textbox, I'd have to modify it in multiple places.

So I'm thinking that the binding within the CellTemplate should look something like this (note that we're using '.' for the binding path):

            Text="{Binding Path=., StringFormat='c', Mode=OneWay}"

And then somehow set the datacontext from the DataGridTemplateColumn declaration – but I can’t see how to do it.

Any idea how to do this?

Webreaper
  • 509
  • 4
  • 18
  • This is a difficult question, a possible idea might be to create a class called ParameterizedDataGridTemplateColumn adding only a DependencyProperty called say ContentBindingName then use a relativesource binding inside the datatemplate. This will be difficult though as inheriting DataGridTemplateColumn is not very straightforward – jimmyjambles Jun 29 '12 at 16:02

2 Answers2

1

@Webreaper: If I understand your idea correctly, then you and I are running into the same stuff. I haven't tried my version of the solution, basically, I will bind the path property of a binding to the DataGridTemplateColumn's SortMemberPath.

<DataGrid>
....
     <DataGridTemplateColumn CellTemplate={StaticResource CellTemplateKey} />
....
</DataGrid>

Where CellTemplateKey is defined somewhere (in App.xaml, for example):

<DataTemplate x:Key="CellTemplateKey">
    <TextBlock Binding="{Binding Source={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGridRow}, Path={Binding Source={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGridTemplateColumn, Path=SortMemberPath}}}}" />
</DataTemplate>

I'll check and update this later. I hope the idea is helpful somehow. I may look into Dyna

Khanh Hua
  • 1,086
  • 1
  • 14
  • 22
0

For this you can use DataTemplateSelector which is actually pretty straightforward to implement.
If you need some further explanations and examples - let me know.

Anatolii Gabuza
  • 6,184
  • 2
  • 36
  • 54
  • Oh, that's neat. So essentially write a DataTemplateSelector and assign it to the CellTtemplateSelector in the XAML, and it can programmatically apply the right template based on some logic? Only problem is, does the logic have to be in code-behind in the DataTemplateSelector, or is it possible to define one in XAML using triggers or something similar? If you have any examples I'd be very grateful. – Webreaper Aug 14 '12 at 07:46