Jmyster
Jmyster

Reputation: 995

How to bind through to a template

I am trying to add a TextBox (and ComboBox when I get this working) to the default DataGridColumnHeader and have done so like below. This is in an application ResourceDirectory^:

<Style x:Key="DataGridColumnHeaderStyle_TextBox" TargetType="{x:Type DataGridColumnHeader}">
   <Setter Property="VerticalContentAlignment" Value="Center"/>
   <Setter Property="Template">
      <Setter.Value>
         <ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
            <Themes:DataGridHeaderBorder Grid.Row="0" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" IsClickable="{TemplateBinding CanUserSort}" IsPressed="{TemplateBinding IsPressed}" IsHovered="{TemplateBinding IsMouseOver}" Padding="{TemplateBinding Padding}" SortDirection="{TemplateBinding SortDirection}" SeparatorBrush="{TemplateBinding SeparatorBrush}" SeparatorVisibility="{TemplateBinding SeparatorVisibility}">
               <Grid>
                  <Grid.RowDefinitions>
                     <RowDefinition Height="*"/>
                     <RowDefinition Height="*"/>
                  </Grid.RowDefinitions>
                  <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                  <TextBox Grid.Row="1" Text="" HorizontalAlignment="Stretch" BorderThickness="1" />
                  <Thumb x:Name="PART_LeftHeaderGripper" HorizontalAlignment="Left" Style="{StaticResource ColumnHeaderGripperStyle}"/>
                  <Thumb x:Name="PART_RightHeaderGripper" HorizontalAlignment="Right" Style="{StaticResource ColumnHeaderGripperStyle}"/>
               </Grid>
            </Themes:DataGridHeaderBorder>
         </ControlTemplate>
      </Setter.Value>
   </Setter>
</Style>

In my Window DataGrid I have the following:

<DataGridTextColumn Header="PO Number" Binding="{Binding PO_Number}" HeaderStyle="{DynamicResource DataGridColumnHeaderStyle_TextBox}"/>

This looks the way I want at the moment, and the Header text binds to the ContentPresenter.

Question

How do I set it up so I can bind to the newly add TextBox (or any object for that matter) like this: HeaderTemplate.TextBox.Text="{Binding SomeSubTotalClass}"

<DataGridTextColumn Header="PO Number" HeaderTemplate.TextBox.Text="{Binding SomeSubTotalClass}" Binding="{Binding PO_Number}" HeaderStyle="{DynamicResource DataGridColumnHeaderStyle_TextBox}"/>

Upvotes: 0

Views: 73

Answers (1)

thatguy
thatguy

Reputation: 22089

You can create a set of attached properties for your custom column header.

public static class DataGridHeaderProperties
{
   public static readonly DependencyProperty TextProperty = DependencyProperty.RegisterAttached(
      "Text", typeof(string), typeof(DataGridHeaderProperties));

   public static string GetText(DependencyObject dependencyObject)
   {
      return (string)dependencyObject.GetValue(TextProperty);
   }

   public static void SetText(DependencyObject dependencyObject, string value)
   {
      dependencyObject.SetValue(TextProperty, value);
   }
}

Then adapt your column header template so that the Text property of the TextBox binds to this attached property that is specified on the corresponding data grid column definition.

<TextBox Grid.Row="1" Text="{Binding Column.(local:DataGridHeaderProperties.Text), RelativeSource={RelativeSource AncestorType={x:Type DataGridColumnHeader}}}" HorizontalAlignment="Stretch" BorderThickness="1" />

Now, set the property on your column definition. Below, there is only a static text for testing, but you can bind the property any way you like.

<DataGridTextColumn Header="PO Number"
                    Binding="{Binding PO_Number}"
                    HeaderStyle="{StaticResource DataGridColumnHeaderStyle_TextBox}"
                    local:DataGridHeaderProperties.Text="My custom text"/>

However, note that columns are not part of the visual tree and do not have a data context to bind to, so you have to use a binding proxy or another mechanism. This is a well known issue for the DataGrid and not the core of this question, but there are already solutions on StackOverflow.

You can extend this solution for any other controls in the column header, like a ComboBox. You just have to add additional attached properties, e.g. for the ItemsSource, SelectedItem and so on, but you should also invest some to refine the concept. It seems odd to put these kinds of controls in column headers. It could harm the usability of your application. Maybe there is a more suitable approach that fits your requirements.

Upvotes: 1

Related Questions