58

I have a regular DataGrid from WPF 4.0 RTM, where I put data from a database. In order to make clean & light style of DataGrid I use a tall/high rows and by default DataGrid aligns row content in top vertical position, but I want to set a center vertical alignment.

I already tried to use this property

VerticalAlignment="Center"

in DataGrid options, but it doesn't help me.

Here is an example of XAML-code, describing my DataGrid without center vertical alignment:

<DataGrid x:Name="ContentDataGrid"
    Style="{StaticResource ContentDataGrid}"
    ItemsSource="{Binding}"
    RowEditEnding="ContentDataGrid_RowEditEnding">
<DataGrid.Columns>
    <DataGridTextColumn Header="UserID"
            Width="100"
            IsReadOnly="True"
            Binding="{Binding Path=userID}" />
    <DataGridTextColumn Header="UserName"
            Width="100"
            Binding="{Binding Path=userName}" />
    <DataGridTextColumn Header="UserAccessLevel"
            Width="100"
            Binding="{Binding Path=userAccessLevel}" />
    <DataGridTextColumn Header="UserPassword"
            Width="*"
            Binding="{Binding Path=userPassword}" />
</DataGrid.Columns>
</DataGrid>

Result of executing this code:

alt text

As you can see all row content has top vertical align.

What do I have to add in order to get center vertical alignment of each row content?

Mike B.
  • 10,955
  • 19
  • 76
  • 118
  • Another approach, using DataGridColumn inheritance: http://blog.smoura.com/wpf-toolkit-datagrid-part-iii-playing-with-datagridcolumns-and-datagridcells/ - allows to simply set VerticalAlignment property on the inherited column - requires inheriting from each used column type, so that's quite a limitation. Maybe somebody will translate it into behaviour? – surfen Dec 19 '11 at 15:32

9 Answers9

117

Complete solution of this issue at MSDN: Vertical alignment of DataGrid row content.

In brief, in style-file set:

<!--body content datagrid cell vertical centering-->
<Style x:Key="Body_Content_DataGrid_Centering"
        TargetType="{x:Type DataGridCell}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type DataGridCell}">
                <Grid Background="{TemplateBinding Background}">
                    <ContentPresenter VerticalAlignment="Center" />
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

In window file:

<DataGrid x:Name="ContentDataGrid"
        Style="{StaticResource ContentDataGrid}"
        CellStyle="{StaticResource Body_Content_DataGrid_Centering}"
        ItemsSource="{Binding}"
        RowEditEnding="ContentDataGrid_RowEditEnding">
    <DataGrid.Columns>
        <DataGridTextColumn Header="UserID"
                Width="100"
                IsReadOnly="True"
                Binding="{Binding Path=userID}" />
        <DataGridTextColumn Header="UserName"
                Width="100"
                Binding="{Binding Path=userName}" />
        <DataGridTextColumn Header="UserAccessLevel"
                Width="100"
                Binding="{Binding Path=userAccessLevel}" />
        <DataGridTextColumn Header="UserPassword"
                Width="*"
                Binding="{Binding Path=userPassword}" />
    </DataGrid.Columns>
</DataGrid>

This will give you a wanted result:

alt text

Mike B.
  • 10,955
  • 19
  • 76
  • 118
  • 30
    i know this is an old answer. But isn't this a lot of work for simple centering of content? – neebz Feb 20 '11 at 12:03
  • 4
    Unfortunatly, I didn't find any other simple solution, if you have such, please, share you knowledge. – Mike B. Feb 28 '11 at 23:20
  • The main reason is because the DataGrid contains DataGridRow who contains DataGridCell who containt Controls. You want these controls be be vertical center. That's what Toucki is doing. – Philippe Lavoie Jun 08 '11 at 20:54
  • Note that there is also DataGridColumn.CellStyle property. It is useful if one wants to apply Centered Cell Style to the DataGrid but want 1 or 2 columns Stretched (for example DataGridTemplateColumn with custom background color and centered TextBlock) - define new CellStyle with VerticalAlignment Stetched, and assign it to those columns. – surfen Dec 19 '11 at 15:24
  • Nice , I needed HorizontalAlignment="Center" also for center , – Zakos Aug 29 '12 at 20:14
  • 2
    IMO instead of hardcoding the "center" value it might be worthwhile to bind the Cell's VerticalContentAlignment value inside the template `VerticalAlignment="{TemplateBinding VerticalContentAlignment}"` instead, that way it will start respect it when set later and you can make this the set-once default style in app.xaml and stop worrying about it. – wondra Jan 24 '20 at 10:28
55

To set individual text alignments you can use:

<DataGridTextColumn.ElementStyle>
   <Style TargetType="TextBlock">
       <Setter Property="TextAlignment" Value="Center" />
   </Style>
</DataGridTextColumn.ElementStyle>
jamier
  • 772
  • 6
  • 9
  • 10
    Yes it works (Use VerticalAlignment, since TextAlignment is for Horizontal text positioning), but you'll have to set element Styles for all columns (Checkbox columns and comboboxcolumns will need to have different styles). – surfen Dec 18 '11 at 17:58
  • It like this way, because it does not break the grid lines if you have those enabled. – Lars Holm Jensen Feb 22 '12 at 09:51
22

The following code will vertically align the content of a DataGridTextColumn cell:

<DataGridTextColumn.ElementStyle>
    <Style TargetType="TextBlock">
        <Setter Property="VerticalAlignment" Value="Center"></Setter>
    </Style>
</DataGridTextColumn.ElementStyle>

Edit: I've come back to this problem and found the solution below to work better, it will center the contents of all the cells in DataGridTextRows both horizontally and vertically.

<UserControl.Resources>    
    <ResourceDictionary>
        <Style TargetType="DataGridCell">
            <Setter Property="HorizontalAlignment" Value="Stretch"></Setter>
            <Setter Property="VerticalAlignment" Value="Stretch"></Setter>
            <Setter Property="VerticalContentAlignment" Value="Stretch"></Setter>
            <Setter Property="TextBlock.TextAlignment" Value="Center"></Setter>
            <Setter Property="TextBlock.VerticalAlignment" Value="Center"></Setter>
        </Style>    
    </ResourceDictionary>
</UserControl.Resources>
mhansen
  • 392
  • 4
  • 12
  • 2
    Does NOT work. Try setting the DataGrid RowHeight=100 to make rows higher than default height. the gridlines will look totally weird. Your first solution (DataGridTextColumn.ElementStyle) works better for me. – joedotnot May 29 '15 at 00:24
17

This one works for me

 <DataGrid.CellStyle>
   <Style TargetType="DataGridCell">              
     <Setter Property="TextBlock.TextAlignment" Value="Center"/>
     <Setter Property="Template">
       <Setter.Value>
         <ControlTemplate TargetType="{x:Type DataGridCell}">
           <Grid Background="{TemplateBinding Background}">
             <ContentPresenter VerticalAlignment="Center"/>
           </Grid>
         </ControlTemplate>
       </Setter.Value>
     </Setter>
   </Style>
</DataGrid.CellStyle>
Massimiliano Kraus
  • 3,214
  • 5
  • 20
  • 40
Justin Adrias
  • 341
  • 3
  • 5
15

You could also do without overriding the ControlTemplate:

    <Style TargetType="{x:Type DataGridCell}">
    <Setter Property="VerticalAlignment" Value="Center" />
    </Style>
usefulBee
  • 8,074
  • 7
  • 46
  • 71
  • 1
    Don't know why this answer didn't have any votes. It's much simpler than the more complex answers, and works fine! – Avrohom Yisroel Apr 10 '14 at 20:21
  • 8
    This answer is only working when you don't have vertical grid lines. Otherwise the gridlines will get a gap if you set the RowHeight property. – Sven Sep 01 '14 at 17:29
6

The attribute value VerticalAlignment="Center" will center the DataGrid within its parent element.

You probably want VerticalContentAlignment.

Nick Desjardins
  • 12,393
  • 3
  • 15
  • 10
3

Building on Jamier's answer, the following code did the trick for me when using auto-generated columns:

Style VerticalCenterStyle = new Style();

public MainWindow()
{
  // This call is required by the designer.
  InitializeComponent();

  VerticalCenterStyle.Setters.Add(new Setter(VerticalAlignmentProperty, VerticalAlignment.Center));
}

private void DataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{   
  if (e.Column is DataGridTextColumn) {
    ((DataGridTextColumn)e.Column).ElementStyle = VerticalCenterStyle;
  }
}
dotNET
  • 28,678
  • 19
  • 120
  • 206
2

This is my simple solution and it just works perfectly

<DataGridTemplateColumn Header="Hello" Width="200">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <TextBlock Text="World!" TextAlignment="Center" VerticalAlignment="Center"/>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

I set the width to 200 so you can notice the difference.

Beyondo
  • 2,118
  • 1
  • 10
  • 33
2

Just if someone might need it as i did..

To only affect a single column you could use the 'ElementStyle' Property:

<DataGrid ItemsSource="{Binding}">
    <DataGrid.Resources>
        <Style x:Key="DataGridVerticalText" TargetType="TextBlock">
            <Setter Property="VerticalAlignment" Value="Center" />
        </Style>
    </DataGrid.Resources>
    <DataGrid.Columns>
        <DataGridTextColumn Header="Header Title" Binding="{Binding}" ElementStyle="{StaticResource DataGridVerticalText}" />
    </DataGrid.Columns>
</DataGrid>
Fresch
  • 57
  • 10