Bespoke DataGridColumnHeader problem

Oct 22, 2008 at 5:30 PM
I'm using a DataTemplate to add a button to the column header, when the button is clicked I want to know which column the button was clicked on. Is there any way in the click event handler for the button to find out what column header the button is for? I stamp the Tag with the {Binding} which gives me the Header property which I could use but its not nice.

Here is the xaml I'm using

            <Style x:Key="ColumnHeaderStyle" TargetType="{x:Type dg:DataGridColumnHeader}">
                <Setter Property="ContentTemplate">
                    <Setter.Value>
                        <DataTemplate>
                            <Border Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor,
                                         AncestorType={x:Type dg:DataGridColumnHeader}}, Path=Width}"
                                    >                                
                                <Grid  HorizontalAlignment="Center">
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="4*" />
                                        <ColumnDefinition Width="*" />
                                    </Grid.ColumnDefinitions>
                                    <TextBlock Text="{Binding}" Margin="0,0,18,0" />
                                    <Button Grid.Column="1"
                                        Click="OnHdrButtonClick"
                                        Opacity="1"
                                        MinWidth="12"
                                        ToolTip="Click to filter"
                                        Tag="{Binding}"
                                       >
                                        <Path x:Name="SortDescIconElement"
                                          Fill="#FF313131" Stroke="#FF313131"
                                          Stretch="Uniform" Width="8"
                                          StrokeThickness="0.5" StrokeLineJoin="Round" Data="F1 M -5.215,0.0L 5.215,0.0L 0,6.099L -5.215,0.0 Z ">
                                        </Path>
                                    </Button>
                                </Grid>
                            </Border>
                        </DataTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
Coordinator
Oct 22, 2008 at 6:32 PM

If the event handler is used only for these buttons in DataGridColumnHeaders, then you can walk the visual tree up starting from the button until you reach an instance of DataGridColumnHeader. VisualTreeHelper.GetParent would be useful. Following is the helper method.....

        T FindVisualParent<T>(UIElement element) where T : UIElement
        {
            UIElement parent = element;
            while (parent != null)
            {
                T correctlyTyped = parent as T;
                if (correctlyTyped != null)
                {
                    return correctlyTyped;
                }
                parent = VisualTreeHelper.GetParent(parent) as UIElement;
            }
            return null;
        }

Your click handler would be...

    OnHdrButtonClick(...)
    {
        DataGridColumnHeader header = FindVisualParent<DataGridColumnHeader>(<button instance>);
        if(header != null)
        {
            ....
        }
    }

Coordinator
Oct 22, 2008 at 6:38 PM
This post should help you out as well, http://blogs.msdn.com/vinsibal/archive/2008/09/16/wpf-datagrid-styling-rows-and-columns-based-on-header-conditions-and-other-properties.aspx.
Oct 23, 2008 at 10:09 AM
Thanks Guys, worked perfectly.