c# - TextBlock 文本未在 DataGridCell 中垂直居中

标签 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。

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

最佳答案

使用 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}"/>

然后我们可以改变VerticalContentAlignmentHorizontalContentAlignmentDataGridCell的风格更改对齐方式。

这意味着如果使用 XAML 代码,只需附加上述代码即可解决您的解决方案。但如果要使用代码隐藏,当然会更长更复杂。

在这里,我向您介绍2种解决方案。首先为 ControlTemplate 构建 VisualTree并为 Template 设置该模板DataGridCell的属性(property):

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

第二种解决方案是使用 XamlReader要直接解析 XAML 代码,这意味着我们需要将之前给出的确切 XAML 代码保存在一个字符串中,并且 XamlReader将解析该字符串,给出一个 Style 的实例:

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 代码。 WPF 中的许多功能主要是为 XAML 代码设计的,因此使用代码隐藏当然并不简单,而且通常很冗长。

注意:XAML我在开头发布的代码不是 DataGridCell 的完整默认样式, 它还有一些 Triggers .这意味着代码可能会更长,抱歉,这是完整的默认 XAML 代码:

<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仍然有效:

//change the highlight selected brush to Red (default by blue).
yourDataGrid.Resources.Add(SystemColors.HighlightBrushKey, Brushes.Red);

关于c# - TextBlock 文本未在 DataGridCell 中垂直居中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25508586/

相关文章:

c# - 代码生成时遇到 VS2015 错误,更改未提交到源

c# - 使用 MahApps.Metro 的 WPF CheckComboBox 样式

c# - 如何使用 C#/WPF 录制音频?

c# - 创建 UWP 应用程序时如何使用 C# 更改 image.source?

c# - 为什么我应该更喜欢使用 API 异步函数而不是用 Task.Run 包装同步函数?

c# - react 性 : Converting merged IObservable's into one stream that acts like BehaviorSubject

c# - 如何在 WPF MenuItem Checkbox 中设置 IsThreeState=True?

c# - 在Silverlight控件中支持文本内容吗?

wpf - 冷启动性能 WPF

c# - SqlCommand 是否优化了参数化的sql 语句?