数据表格行内容垂直对齐

64

我有一个来自WPF 4.0 RTM的常规DataGrid,其中我从数据库中获取数据。为了制作干净且轻量化的DataGrid样式,我使用高行,并且默认情况下DataGrid将行内容对齐到顶部垂直位置,但我想设置居中垂直对齐。

我已经尝试过使用此属性

VerticalAlignment="Center"

我在DataGrid选项中找到了一个属性,但它对我没有帮助。

这里是一个XAML代码示例,描述了我的DataGrid而没有居中垂直对齐:

<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>

执行这段代码的结果:

alt text

正如您所看到的,所有行的内容都是顶部对齐。

为了使每一行的内容垂直居中,我需要添加什么?


另一种方法是使用DataGridColumn继承:http://blog.smoura.com/wpf-toolkit-datagrid-part-iii-playing-with-datagridcolumns-and-datagridcells/ - 允许在继承的列上简单设置VerticalAlignment属性 - 需要从每个使用的列类型进行继承,因此这是相当有限制性的。也许有人会将其转换为行为? - surfen
9个回答

130

此问题的完整解决方案可在MSDN上找到:DataGrid行内容的垂直对齐

简而言之,在样式文件中设置:

<!--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>

在 Windows 系统中的文件:

<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>

这将会给你想要的结果:

alt text


35
我知道这是一个旧回答。但是为了简单地将内容居中,是否会增加很多工作量呢? - neebz
4
很遗憾,我没有找到其他简单的解决方案,如果你有,请分享你的知识。 - Mike
主要原因是DataGrid包含DataGridRow,DataGridRow包含DataGridCell,DataGridCell包含控件。您希望这些控件垂直居中。这就是Toucki正在做的事情。 - Philippe Lavoie
请注意还有DataGridColumn.CellStyle属性。如果想将Centered Cell样式应用于DataGrid但想要1或2列 Stretched的话(例如具有自定义背景色和居中的TextBlock的DataGridTemplateColumn),可以定义新的CellStyle,并将其分配给这些列。该属性非常实用,设置VerticalAlignment为Stretched即可。 - surfen
很好,我还需要HorizontalAlignment="Center"来居中,<ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center" /> - Zakos
2
我认为,与其硬编码“center”值,将单元格的VerticalContentAlignment值绑定到模板中 VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 可能会更有价值。这样,当稍后设置时,它就会开始尊重它,并且您可以在app.xaml中将其作为一次性默认样式设置并停止担心它。 - wondra

59

要设置单个文本的对齐方式,您可以使用:

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

12
可以使用VerticalAlignment,因为TextAlignment是用于水平文本定位的。但是,您需要为所有列设置元素样式(复选框列和组合框列需要具有不同的样式)。 - surfen
2
这样做是因为如果你启用了网格线,它不会破坏网格线。 - Lars Holm Jensen

22
下面的代码将垂直对齐DataGridTextColumn单元格的内容:
<DataGridTextColumn.ElementStyle>
    <Style TargetType="TextBlock">
        <Setter Property="VerticalAlignment" Value="Center"></Setter>
    </Style>
</DataGridTextColumn.ElementStyle>

编辑:我再次回到这个问题,并发现下面的解决方案效果更好,它将水平和垂直地使DataGridTextRows中的所有单元格内容居中。

<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>

5
不起作用。尝试将DataGrid RowHeight设置为100,使行的高度高于默认高度。网格线看起来会完全不同。你的第一个解决方案(DataGridTextColumn.ElementStyle)对我更有效。 - joedotnot

20

这个对我有用

 <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>

16

你也可以不必覆盖控件模板:

    <Style TargetType="{x:Type DataGridCell}">
    <Setter Property="VerticalAlignment" Value="Center" />
    </Style>

1
不知道为什么这个答案没有任何投票。它比更复杂的答案简单得多,而且运行良好! - Avrohom Yisroel
11
只有在没有竖直网格线时,此答案才有效。否则,如果设置行高属性,则网格线会出现间隙。 - Sven

5
属性值VerticalAlignment="Center"将使DataGrid在其父元素中垂直居中。
您可能需要使用VerticalContentAlignment

4

如果有人需要,可以像我一样使用以下方法来只影响单个列:

您可以使用“ElementStyle”属性:

<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>

3

在Jamier的答案基础上,以下代码对于我使用自动生成列时起到了作用:

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;
  }
}

2
这是我简单的解决方案,它完美地运行。原始答案翻译成“最初的回答”。
<DataGridTemplateColumn Header="Hello" Width="200">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <TextBlock Text="World!" TextAlignment="Center" VerticalAlignment="Center"/>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

我把宽度设置为200,这样你就能看到区别了。最初的回答。

1
简单易用,也能正常工作。使用静态资源使其样式更易于定制。 - Hexum064

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接