Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 3496910
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 18, 20262026-05-18T12:18:24+00:00 2026-05-18T12:18:24+00:00

In my App.xaml file, I have the following code to allow double-decker column headers

  • 0

In my App.xaml file, I have the following code to allow “double-decker” column headers in DataGrids.

XAML:

<adv:ColumnHeaderFontSizeToMaxHeightConverter x:Key="columnHeaderFontSizeToMaxHeightConverter" />
<DataTemplate x:Key="WrappingDataGridColumnHeaderTemplate" DataType="{x:Type sys:String}">
    <TextBlock TextWrapping="WrapWithOverflow"
               Text="{Binding}"
               ToolTip="{Binding}"
               MaxHeight="{Binding Path=FontSize, Mode=OneWay,
                                   RelativeSource={RelativeSource Self},
                                   Converter={StaticResource columnHeaderFontSizeToMaxHeightConverter} }" />
</DataTemplate>

Converter:

internal class ColumnHeaderFontSizeToMaxHeightConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter,
        CultureInfo culture)
    {
        Debug.Assert(value.GetType() == typeof(double));

        // We want to have up to 2 lines of text here plus a little bit of space for margins, etc
        // WPF will automatically use the smallest height required
        return (double)value * 2.9;
    }

    public object ConvertBack(object value, Type targetType, object parameter,
        CultureInfo culture)
    {
        Debug.Assert(false);
        throw new NotImplementedException();
    }
}

However, the automatic column resizing that the DataGrid class provides on double clicking the column separators does not take into account the fact that the headers can now get even smaller with word wrapping.

For example, say you have a column with a long header and short values like this:

| Long Header     |
-------------------
| A               |
| B               |
| C               |

Double clicking on the separator will result in this:

| Long Header |
---------------
| A           |
| B           |
| C           |

But what what would be even better is if it would result in this:

| Long   |
| Header |
----------
| A      |
| B      |
| C      |

My question is this:

Is there a way to provide a “hint” to the automatic resizing to let it know that it can go even smaller? Or, will I have to completely reimplement the automatic-resizing-on-double-click logic?

EDIT: With Malaek’s help, I’ve updated my code as follows, but one problem still remains. It doesn’t play nicely with my MaxHeight and 3 or more words. The first double click has part of the header hidden, yet it reappears on the second double click even though the column doesn’t change width. I’ll post the code I’ve been using shortly.

The DataGrid xaml:

<DataGrid.Resources>
    ...
    <Style TargetType="{x:Type DataGridColumnHeader}"
           BasedOn="{StaticResource {x:Type DataGridColumnHeader}}">
        <Setter Property="ContentTemplate" Value="{StaticResource WrappingDataGridColumnHeaderTemplate}" />
        <EventSetter Event="SizeChanged" Handler="DataGridColumnHeader_SizeChanged"/>
        <EventSetter Event="Loaded" Handler="DataGridColumnHeader_Loaded" />
    </Style>
    ...
</DataGrid.Resources>

DataGrid code behind:

private void RightThumb_PreviewMouseDoubleClick(object sender, MouseButtonEventArgs e)
{
    Thumb thumb = sender as Thumb;
    DataGridColumnHeader dataGridColumnHeader = VisualTreeHelpers.GetVisualParent<DataGridColumnHeader>(thumb);
    DataGridColumn column = dataGridColumnHeader.Column;
    UpdateColumnForResize(column);
}

private void LeftThumb_PreviewMouseDoubleClick(object sender, MouseButtonEventArgs e)
{
    Thumb thumb = sender as Thumb;
    DataGridColumnHeader dataGridColumnHeader = VisualTreeHelpers.GetVisualParent<DataGridColumnHeader>(thumb);
    DataGridColumn column = this.Columns.FirstOrDefault(
        c => c.DisplayIndex == dataGridColumnHeader.Column.DisplayIndex - 1);
    UpdateColumnForResize(column);
}

private void UpdateColumnForResize(DataGridColumn column)
{
    if (column != null)
    {
        column.Width = column.Width.DisplayValue;
        string header = (string)column.Header;

        if (header.Contains("\r\n"))
            return;

        int middle = header.Length / 2;
        int closestToMiddle = -1;
        for (int i = 0; i < header.Length; ++i)
        {
            if (header[i] == ' ')
            {
                if (closestToMiddle == -1)
                    closestToMiddle = i;
                else if (Math.Abs(i - middle) < Math.Abs(closestToMiddle - middle))
                    closestToMiddle = i;
            }
        }

        if (closestToMiddle != -1)
        {
            StringBuilder newHeader = new StringBuilder(header);
            newHeader.Replace(" ", "\r\n", closestToMiddle, 1);
            column.Header = newHeader.ToString();
        }
    }
}

private void DataGridColumnHeader_SizeChanged(object sender, SizeChangedEventArgs e)
{
    DataGridColumnHeader columnHeader = sender as DataGridColumnHeader;
    DataGridColumn column = columnHeader.Column;
    if (column != null && column.Header.ToString().IndexOf("\r\n") >= 0)
    {
        column.Header = column.Header.ToString().Replace("\r\n", " ");
        column.Width = column.Width.DisplayValue;
    }
}

private void DataGridColumnHeader_Loaded(object sender, EventArgs e)
{
    DataGridColumnHeader columnHeader = sender as DataGridColumnHeader;
    Thumb thumb = columnHeader.Template.FindName("PART_RightHeaderGripper", columnHeader) as Thumb;

    if (thumb != null)
        thumb.PreviewMouseDoubleClick += RightThumb_PreviewMouseDoubleClick;

    thumb = columnHeader.Template.FindName("PART_LeftHeaderGripper", columnHeader) as Thumb;

    if (thumb != null)
        thumb.PreviewMouseDoubleClick += LeftThumb_PreviewMouseDoubleClick;
}

EDIT2: Apparently the problem is a little more subtle. The header “Last Updated On” triggers it, but “Last Updated By” doesn’t. I’m still investigating.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-18T12:18:25+00:00Added an answer on May 18, 2026 at 12:18 pm

    I think you’ll have to re-template the DataGridColumnHeader in order to get access to the auto-sizing event. The only thing that’s actually happening in the auto-size event is that the DataGridColumn get its Width set to Auto so if we can preview that event, and replace every ‘ ‘ with a linebreak ‘\r\n’ we can get it to wrap the Text for us. Then we can change it back in the SizeChanged event. I also added a ContentTemplate for the DataGridColumnHeader when I was trying this out.

    Ofcourse, this way will only work if you’ll have no linebreaks in the ColumnHeaders to begin with, otherwise it’ll get messed up but hopefully you can still use it somehow.

    <DataGrid ...>
        <DataGrid.Resources>
            <Style x:Key="ColumnHeaderGripperStyle" TargetType="{x:Type Thumb}">
                <Setter Property="Width" Value="8"/>
                <Setter Property="Background" Value="Transparent"/>
                <Setter Property="Cursor" Value="SizeWE"/>
                <EventSetter Event="PreviewMouseDoubleClick" Handler="Thumb_PreviewMouseDoubleClick"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type Thumb}">
                            <Border Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}"/>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
            <Style TargetType="{x:Type DataGridColumnHeader}">
                <EventSetter Event="SizeChanged" Handler="DataGridColumnHeader_SizeChanged"/>
                <Setter Property="VerticalContentAlignment" Value="Center"/>
                <Setter Property="ContentTemplate">
                    <Setter.Value>
                        <DataTemplate>
                            <TextBlock TextWrapping="WrapWithOverflow" Text="{Binding}"></TextBlock>
                        </DataTemplate>
                    </Setter.Value>
                </Setter>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
                            <Grid>
                                <Microsoft_Windows_Themes:DataGridHeaderBorder 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}">
                                    <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                                </Microsoft_Windows_Themes:DataGridHeaderBorder>
                                <Thumb x:Name="PART_LeftHeaderGripper" HorizontalAlignment="Left" Style="{StaticResource ColumnHeaderGripperStyle}"/>
                                <Thumb x:Name="PART_RightHeaderGripper" HorizontalAlignment="Right" Style="{StaticResource ColumnHeaderGripperStyle}"/>
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </DataGrid.Resources>
        <!-- ... -->
    </DataGrid>
    

    Code behind EventHandlers. Change to \r\n in preview and change back to ‘ ‘ in SizeChanged.

    void Thumb_PreviewMouseDoubleClick(object sender, MouseButtonEventArgs e)
    {
        Thumb thumb = sender as Thumb;
        DataGridColumnHeader dataGridColumnHeader = VisualTreeHelpers.GetVisualParent<DataGridColumnHeader>(thumb);
        DataGridColumn column = dataGridColumnHeader.Column;
        if (column != null)
        {
            column.Width = column.Width.DisplayValue;
            column.Header = column.Header.ToString().Replace(" ", "\r\n");
        }
    }
    void DataGridColumnHeader_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        DataGridColumnHeader columnHeader = sender as DataGridColumnHeader;
        DataGridColumn column = columnHeader.Column;
        if (column != null && column.Header.ToString().IndexOf("\r\n") >= 0)
        {
            column.Header = column.Header.ToString().Replace("\r\n", " ");
            column.Width = column.Width.DisplayValue;
        }
    }
    

    An implementation of GetVisualParent

    public static T GetVisualParent<T>(object childObject) where T : Visual
    {
        DependencyObject child = childObject as DependencyObject;
        // iteratively traverse the visual tree
        while ((child != null) && !(child is T))
        {
            child = VisualTreeHelper.GetParent(child);
        }
        return child as T;
    }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have the following custom defined Button defined in my App.xaml file. <Style x:Key=DispatchListCallButton
I have the following App.xaml file: <Application x:Class=MiniDeviceConfig.App xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml StartupUri=MiniDeviceConfig.xaml> <Application.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries>
I have the following set of code in my App.xaml: <Application.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary
I have so many styles in the app.xaml file and now it's close to
I have custom classes that I currently instantiate within App.xaml as resources. I want
Guys, I have a basic WPF application. Contains App.xaml as always and a Mainwindow.xaml.
I have a multi-xaml metro app. I want to switch between xaml by button
Bellow is the code behind and the Xaml for a demo app to review
I have an XML file with the following structure: <Products> <Product name=MyProduct1> <Components> <Component
I override borders CornerRadius as a default style in the app.xaml file (like below)

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.