Skip to content

Alignment of WPF DataGrid header

April 20, 2011

In the previous post I described how you can wrap the text in the column header of the WPF DataGrid. In this post we are going to extend the style so is also possible to align the header text. The default alignment of the header text is left.

First we create 3 styles, one for each alignment possibility (left, center and right alignment).

<Style x:Key="LeftAlignmentColumnHeaderStyle" TargetType="{x:Type DataGridColumnHeader}" BasedOn="{StaticResource WrappedColumnHeaderStyle}">
    <Setter Property="HorizontalContentAlignment" Value="Left"/>
</Style>

<Style x:Key="CenterAlignmentColumnHeaderStyle" TargetType="{x:Type DataGridColumnHeader}" BasedOn="{StaticResource WrappedColumnHeaderStyle}">
    <Setter Property="HorizontalContentAlignment" Value="Center"/>
</Style>

<Style x:Key="RightAlignmentColumnHeaderStyle" TargetType="{x:Type DataGridColumnHeader}" BasedOn="{StaticResource WrappedColumnHeaderStyle}">
    <Setter Property="HorizontalContentAlignment" Value="Right"/>
</Style>

In the styles above we use the BasedOn property so the style is based on the WrappedColumnHeaderStyle we created in the previous post. The property HorizontalContentAligment is used for setting the alignment because in the default control template of the DataGridColumnHeader this property is used for aligning the content of the header.

In the column definitions we can set the HeaderStyle to a specific alignment style.

<DataGrid ItemsSource="{Binding }" AutoGenerateColumns="False">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Long header text (alignment = left)" HeaderStyle="{StaticResource LeftAlignmentColumnHeaderStyle}" Width="50" Binding="{Binding Name}"/>
        <DataGridTextColumn Header="Long header text (alignment = center)" HeaderStyle="{StaticResource CenterAlignmentColumnHeaderStyle}" Width="50" Binding="{Binding Name}"/>
        <DataGridTextColumn Header="Long header text (alignment = right)" HeaderStyle="{StaticResource RightAlignmentColumnHeaderStyle}" Width="50" Binding="{Binding Name}"/>
     </DataGrid.Columns>
</DataGrid> 

As you can see in the picture below the header text is aligned.

There is one issue we have to fix. For wrapping the text we make use of a TextBlock. This TextBlock is correctly aligned but when the text is wrapped the text lines in the TextBlock are always aligned to the left within the TextBlock. To solve this we extend the WrappedColumnHeaderStyle with some data triggers which set the TextAlignment property of the TextBlock to the correct value.

<Style x:Key="WrappedColumnHeaderStyle" TargetType="{x:Type DataGridColumnHeader}">
    <Setter Property="ContentTemplate">
        <Setter.Value>
            <DataTemplate>
                <TextBlock x:Name="TextBlock" TextWrapping="Wrap" Text="{Binding}"></TextBlock>
                <DataTemplate.Triggers>
                     <DataTrigger Binding="{Binding Path=HorizontalContentAlignment, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridColumnHeader}}}" Value="Center">
                        <Setter TargetName="TextBlock" Property="TextAlignment" Value="Center"/>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding Path=HorizontalContentAlignment, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridColumnHeader}}}" Value="Left">
                        <Setter TargetName="TextBlock" Property="TextAlignment" Value="Left"/>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding Path=HorizontalContentAlignment, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridColumnHeader}}}" Value="Right">
                        <Setter TargetName="TextBlock" Property="TextAlignment" Value="Right"/>
                    </DataTrigger>
                </DataTemplate.Triggers>
            </DataTemplate>
        </Setter.Value>
    </Setter>
</Style>

As you can see in the picture below also in case the text is wrapped the alignment for all text lines is correct.

About these ads

From → .NET, DataGrid, WPF

7 Comments
  1. Stephen Bickerstaff permalink

    After following this and the previous text wrapping article, I keep getting an unhandled XamlParseException with the text:
    “Provide value on ‘System.Windows.Markup.StaticresourceHolder’ threw an exception.

    The InnerException message is:
    “Cannot find resource named ‘WrappedColumnHeaderStyle’. Resource names are case sensitive.”

    but i’ve even copied and pasted the names and all looks ok.

    Have you come across this before when you were working on this solution?

    • Hello Stephen,

      Have you defined the WrappedColumnHeaderStyle style before using it in another style? The order in the XAML file is important because it is a static resource.

      Example:

      <Style x:Key="WrappedColumnHeaderStyle" TargetType="{x:Type DataGridColumnHeader}"/>
      
      <Style x:Key="LeftAlignmentColumnHeaderStyle" TargetType="{x:Type DataGridColumnHeader}" BasedOn="{StaticResource WrappedColumnHeaderStyle}">
      </Style>
      

      Regards,

      Marcel.

  2. Stephen Bickerstaff permalink

    Hi Marcel,

    Thanks for such a quick response, wasn’t expecting you to get back so quickly. Yes, thats the exact order I have it specified.

    then center and right

    With the WrappedColumnHeaderStyle using the version with the 3 DataTriggers. I have it at the end of my Application Styles Dictionary right before I call:

    and none of those contain anything similar so it’s not a case of being defined twice and not knowing which to go to.

  3. Stephen Bickerstaff permalink

    I had the code segments in there, don’t know why it’s hiding them when I post

    • You can send me an email with the source code so I can look what the problem is.

      • Stephen Bickerstaff permalink

        Where do I find your email address? I’m not registered on LinkedIn.

  4. Stephen Bickerstaff permalink

    Thanks Marcel for your help. For anyone else who comes across the same issue:

    If you have dialogs / DataTemplate defined in a resource dictionary and the above code in another resource dictionary, the styles dictionary must be called from the DataTemplate dictionary. Calling the DataTemplate from the Styles resource dictionary will result in an error as I mentioned above

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: