TextBlock文本不在DataGridCell中垂直居中

时间:2014-08-26 14:38:16

标签: c# wpf xaml datagrid vertical-alignment

我在C#中创建DataGrid(来自代码隐藏/非XAML),但无论我尝试什么,我都无法让文本在数据中垂直居中细胞:

]

我开始时:

var CellStyle = new Style(typeof(DataGridCell)) {
    Setters = {
        new Setter(TextBlock.TextAlignmentProperty, TextAlignment.Center)
    }
};

正确定位单元格并使文本水平居中(根据上面的屏幕截图)。

尝试将文本垂直居中,我知道TextBlock不支持垂直内容对齐,只支持父元素中自己的垂直对齐。

根据这个问题(Text vertical alignment in WPF TextBlock),我试图使用Padding伪造它:

var CellStyle = new Style(typeof(DataGridCell)) {
    Setters = {
        new Setter(TextBlock.PaddingProperty, new Thickness(5)),
        new Setter(TextBlock.TextAlignmentProperty, TextAlignment.Center)
    }
};

这没有任何区别。然后我尝试了这个:

var CellStyle = new Style(typeof(DataGridCell)) {
    Setters = {
        new Setter(DataGridCell.VerticalContentAlignmentProperty, VerticalAlignment.Center),
        new Setter(TextBlock.TextAlignmentProperty, TextAlignment.Center),
        new Setter(TextBlock.VerticalAlignmentProperty, VerticalAlignment.Center)
    }
};

导致:

添加new Setter(DataGridCell.HeightProperty, 50d),会产生屏幕截图#1。

如何在文本数据单元格中垂直居中?

2 个答案:

答案 0 :(得分:5)

使用Blend for Visual Studio,我们为DataGridCell

提供了这种样式
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="BorderThickness" Value="1"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type DataGridCell}">
                <Border BorderBrush="{TemplateBinding BorderBrush}" 
                        BorderThickness="{TemplateBinding BorderThickness}" 
                        Background="{TemplateBinding Background}" 
                        SnapsToDevicePixels="True"                          
                >
                    <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                </Border>
            </ControlTemplate>
        </Setter.Value>
</Setter>

所以看起来没有任何默认支持来更改对齐方式。通常,<ContentPresenter>应该包含以下代码:

<ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                  VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
                  HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>

然后我们可以更改VerticalContentAlignment样式中的HorizontalContentAlignmentDataGridCell来更改路线。

这意味着如果使用XAML代码,只需添加上述代码即可解决您的解决方案。但是如果你想使用代码,它当然会更长,更复杂。

这里我向您介绍2种解决方案。首先为ControlTemplate构建VisualTree,并为Template的{​​{1}}属性设置该模板:

DataGridCell

第二个解决方案是使用//root visual of the ControlTemplate for DataGridCell is a Border var border = new FrameworkElementFactory(typeof(Border)); border.SetBinding(Border.BorderBrushProperty, new Binding("BorderBrush") { RelativeSource = RelativeSource.TemplatedParent }); border.SetBinding(Border.BackgroundProperty, new Binding("Background") {RelativeSource = RelativeSource.TemplatedParent }); border.SetBinding(Border.BorderThicknessProperty, new Binding("BorderThickness") {RelativeSource = RelativeSource.TemplatedParent }); border.SetValue(SnapsToDevicePixelsProperty, true); //the only child visual of the border is the ContentPresenter var contentPresenter = new FrameworkElementFactory(typeof(ContentPresenter)); contentPresenter.SetBinding(SnapsToDevicePixelsProperty, new Binding("SnapsToDevicePixelsProperty") {RelativeSource=RelativeSource.TemplatedParent }); contentPresenter.SetBinding(VerticalAlignmentProperty, new Binding("VerticalContentAlignment") { RelativeSource = RelativeSource.TemplatedParent }); contentPresenter.SetBinding(HorizontalAlignmentProperty, new Binding("HorizontalContentAlignment") {RelativeSource = RelativeSource.TemplatedParent }); //add the child visual to the root visual border.AppendChild(contentPresenter); //here is the instance of ControlTemplate for DataGridCell var template = new ControlTemplate(typeof(DataGridCell)); template.VisualTree = border; //define the style var style = new Style(typeof(DataGridCell)); style.Setters.Add(new Setter(TemplateProperty, template)); style.Setters.Add(new Setter(VerticalContentAlignmentProperty, VerticalAlignment.Center)); style.Setters.Add(new Setter(HorizontalContentAlignmentProperty, HorizontalAlignment.Center)); yourDataGrid.CellStyle = style; 直接解析XAML代码,这意味着我们需要在保存在字符串中之前给出的确切XAML代码,XamlReader将解析该字符串给出实例XamlReader

Style

您可以看到两种解决方案都相当长,但它们实际上是您应该使用后面的代码。这意味着我们应该尽可能多地使用XAML代码。 WPF中的许多功能主要是为XAML代码设计的,因此使用背后的代码当然不是直截了当且通常很冗长。

注意:我在开头发布的var xaml = "<Style TargetType=\"{x:Type DataGridCell}\"><Setter Property=\"VerticalContentAlignment\" Value=\"Center\"/>" + "<Setter Property=\"HorizontalContentAlignment\" Value=\"Center\"/>" + "<Setter Property=\"Template\">" + "<Setter.Value><ControlTemplate TargetType=\"DataGridCell\">" + "<Border BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"{TemplateBinding BorderThickness}\" Background=\"{TemplateBinding Background}\" SnapsToDevicePixels=\"True\">" + "<ContentPresenter SnapsToDevicePixels=\"{TemplateBinding SnapsToDevicePixels}\" VerticalAlignment=\"{TemplateBinding VerticalContentAlignment}\" HorizontalAlignment=\"{TemplateBinding HorizontalContentAlignment}\"/>" + "</Border></ControlTemplate></Setter.Value></Setter></Style>"; var parserContext = new System.Windows.Markup.ParserContext(); parserContext.XmlnsDictionary .Add("","http://schemas.microsoft.com/winfx/2006/xaml/presentation"); parserContext.XmlnsDictionary .Add("x","http://schemas.microsoft.com/winfx/2006/xaml"); yourDataGrid.CellStyle = (Style)System.Windows.Markup.XamlReader.Parse(xaml,parserContext); 代码不是XAML的完整默认样式,它还有一些DataGridCell。这意味着代码可能会更长,抱歉,这是完整的默认XAML代码:

Triggers

但是我刚测试了它,看起来默认样式始终应用于<Style TargetType="{x:Type DataGridCell}"> <Setter Property="Background" Value="Transparent"/> <Setter Property="BorderBrush" Value="Transparent"/> <Setter Property="BorderThickness" Value="1"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type DataGridCell}"> <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True" > <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Center" HorizontalAlignment="Center"/> </Border> </ControlTemplate> </Setter.Value> </Setter> <Style.Triggers> <Trigger Property="IsSelected" Value="True"> <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/> <Setter Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/> </Trigger> <Trigger Property="IsKeyboardFocusWithin" Value="True"> <Setter Property="BorderBrush" Value="{DynamicResource {x:Static DataGrid.FocusBorderBrushKey}}"/> </Trigger> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="IsSelected" Value="true"/> <Condition Property="Selector.IsSelectionActive" Value="false"/> </MultiTrigger.Conditions> <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/> <Setter Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}}"/> </MultiTrigger> <Trigger Property="IsEnabled" Value="false"> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/> </Trigger> </Style.Triggers> </Style> ,它只是被您添加的DataGridCell覆盖(设置相同)属性)。这是测试代码,Setter仍然有效:

Trigger

答案 1 :(得分:1)

我的回答只是总结了King King,以防有人帮忙。在XAML中:

使用CellStyle="{StaticResource CustomCell}"

中的DataGrid媒体资源
<Style x:Key="CustomCell" TargetType="{x:Type DataGridCell}">
    <Setter Property="VerticalContentAlignment" Value="Center" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type DataGridCell}">
                <ContentPresenter VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>