Thursday, February 25, 2016

Right-align textblock in datagrid

Let's suppose you have a datagrid with a column that you want right-aligned. Sounds easy right? Your code behind might look something like this...

Imports System.Collections.ObjectModel
Class MainWindow
    Public Property Amounts As New ObservableCollection(Of Decimal) From {0}
End Class

and your XAML might look like this...

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525"
    DataContext="{Binding RelativeSource={RelativeSource Self}}">
    <DataGrid ItemsSource="{Binding Amounts}">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Amounts" Binding="{Binding}">
                <DataGridTextColumn.ElementStyle>
                    <Style TargetType="TextBlock">
                        <Setter Property="HorizontalAlignment" Value="Right"></Setter>
                    </Style>
                </DataGridTextColumn.ElementStyle>
            </DataGridTextColumn>
        </DataGrid.Columns>
    </DataGrid>
</Window>

The results look like this, which is what we expected.


Now let's put a background on the text block by adding another setter to the element style.

<Setter Property="Background" Value="Yellow"></Setter>


Well that isn't right :-(
The problem is that the text block is only as wide as it needs to be. What if we explicitly set the width to 50px by adding yet another setter?

<Setter Property="Width" Value="50"></Setter>


Wow - so now our cell is yellow but the right-align is broken. If you look carefully you can see the text block is right aligned within the cell but the contents of the text block are left aligned. The HorizontalAlignment property controls how the text block is aligned, not how it's contents are aligned. This is consistent, but a little non-intuitive. But there isn't a HorizontalContentAlignment property on a text block :-(

It turns out there are two simple ways to fix this.
Option 1 is to set the background of the cell. If no background is set for the textblock it is transparent and the cell background bleeds through.

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525"
    DataContext="{Binding RelativeSource={RelativeSource Self}}">
    <DataGrid ItemsSource="{Binding Amounts}">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Amounts" Binding="{Binding}">
                <DataGridTextColumn.ElementStyle>
                    <Style TargetType="TextBlock">
                        <Setter Property="HorizontalAlignment" Value="Right"></Setter>
                    </Style>
                </DataGridTextColumn.ElementStyle>
                <DataGridTextColumn.CellStyle>
                    <Style TargetType="DataGridCell">
                        <Setter Property="Background" Value="Yellow"></Setter>
                    </Style>
                </DataGridTextColumn.CellStyle>
            </DataGridTextColumn>
        </DataGrid.Columns>
    </DataGrid>
</Window>

Option 2 is to set the horizontal alignment to Stretch and set the TextAlignment property to Right. So for text blocks the TextAlignment property replaces the HorizontalContentAlignment property.

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525"
    DataContext="{Binding RelativeSource={RelativeSource Self}}">
    <DataGrid ItemsSource="{Binding Amounts}">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Amounts" Binding="{Binding}">
                <DataGridTextColumn.ElementStyle>
                    <Style TargetType="TextBlock">
                        <Setter Property="HorizontalAlignment" Value="Stretch"></Setter>
                        <Setter Property="TextAlignment" Value="Right"></Setter>
                        <Setter Property="Background" Value="Yellow"></Setter>
                    </Style>
                </DataGridTextColumn.ElementStyle>
            </DataGridTextColumn>
        </DataGrid.Columns>
    </DataGrid>
</Window>



No comments:

Post a Comment