如何使WPF DataGrid单元格右对齐而不使可选择区域在新行变小?

67

我正在使用 WPF4.0 的 DataGrid。当在新行上双击单元格时,一切正常,除非我已经向该列添加了单元格样式。例如,我有一个数字列,我想把数据右对齐,所以 xaml 看起来像这样:

<DataGridTextColumn Binding="{Binding Path=ImpaId}"
                    CellStyle="{StaticResource CellRightAlign}">
     <DataGridTextColumn.Header>
          <TextBlock  Style="{StaticResource DataGridHeader}">Impa</TextBlock>
     </DataGridTextColumn.Header>
</DataGridTextColumn>

共享资源中的样式只是:

<Style x:Key="CellRightAlign">
    <Setter Property="Control.HorizontalAlignment"
            Value="Right" />
</Style>

图中显示了新行的可选择区域,它是一个非常小的蓝色区域。这对用户来说是一个非常小的目标,在新行上,这恰好是他们最可能想要开始的列。

DataGrid cell with tiny width

如果我删除单元格样式,该区域将按预期工作,但我会失去正确的对齐方式。

DataGrid cell with proper width

有人知道如何同时实现这两个效果吗?

我尝试过的事情

  1. 将绑定的TargetNullValue设置为具有某些宽度的格式。这在现有行上有效,但对新行没有效果。
  2. 在列上设置MinWidth,但它不会影响新行可选择区域的宽度。

成功的方法:

根据@AngelWPF的回答,我能够改为使用ElementStyle而不是CellStyle,具体操作如下:

<DataGridTextColumn Binding="{Binding Path=ImpaId}"
                    CellStyle="{StaticResource CellRightAlign}">
成为。
<DataGridTextColumn Binding="{Binding Path=ImpaId}"
                    ElementStyle="{StaticResource CellRightAlign}">

类似的问题,但不知道答案: http://stackoverflow.com/questions/18378515/how-to-make-cell-to-take-full-width-when-aligned-to-right-or-left-in-wpf-grid - digz6666
5个回答

97

您可以将ElementStyle应用于针对TextBlockDataGridTextColumn并右对齐它,这将起作用。

      <DataGridTextColumn Binding="{Binding Path=ImpaId}">
          <DataGridTextColumn.Header>
               <TextBlock  Style="{StaticResource
                                  DataGridHeader}">
                    Impa
               </TextBlock>
          </DataGridTextColumn.Header>
          <DataGridTextColumn.ElementStyle>
              <Style TargetType="{x:Type TextBlock}">
                  <Setter Property="HorizontalAlignment" Value="Right" />
              </Style>
          </DataGridTextColumn.ElementStyle>
      </DataGridTextColumn> 

我只需在外部DataGridTextColumn添加ElementStyle属性并使用现有的CellRightAlign即可将代码最小化。谢谢。 - Tod

24

只是想为以后的代码搜索添加两个示例。

我将其放在xaml文件的顶部:

<UserControl.Resources>
    <Style TargetType="{x:Type TextBlock}" x:Key="RightCell">
        <Setter Property="Background" Value="{Binding Included, Converter={StaticResource BoolToColorConverter}}"/>
        <Setter Property="HorizontalAlignment" Value="Stretch"/>
        <Setter Property="TextAlignment" Value="Right"/>
    </Style>
</UserControl.Resources>

然后在数据网格中:

<DataGridTextColumn Header="Excluded" Binding="{Binding Excluded}" ElementStyle="{StaticResource RightCell}"/>

这将右对齐文本,并仍然启用排序功能。文本框填充了单元格,在这种情况下使用布尔转换器进行着色。


1
完美而简单的“ElementStyle”赋值。 - DRapp
这也修复了一个问题,即按Tab键会在列之间造成“暂停”,非常感谢天才。 - BoarOfGold

6
你可以尝试一个解决方法:
           <DataGridTemplateColumn>
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <Grid Background="White" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
                        <TextBlock HorizontalAlignment="Right" Text="{Binding Path=ImpaId}"/>
                    </Grid>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>

5

我刚刚遇到了类似的问题,并在Blend中重写DataGridCell的样式找到了另一种解决方案。

原始样式中更改的项是Style本身的VerticalAlignmentVerticalContentAlignment设置,以拉伸单元格本身,以及模板属性中的VerticalAlignment="Center"HorizontalAlignment="Right"以对齐内容。将这些值更改为您需要对齐单元格内容的任何内容。

样式的其余部分可以被删除,以便使用基本样式的设置(使用StaticResource样式BasedOn)。但是我保留了由Blend生成的样式。

然后应将此结果XAML代码包含在控件资源中:

<Style TargetType="{x:Type DataGridCell}" BasedOn="{StaticResource ResourceKey={x:Type DataGridCell}}">
    <Setter Property="VerticalAlignment" Value="Stretch" />
    <Setter Property="VerticalContentAlignment" Value="Stretch" />

    <!-- Additional styles, can be removed to fall back to base styles -->
    <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
                        ContentTemplate="{TemplateBinding ContentTemplate}"
                        Content="{TemplateBinding Content}"
                        ContentStringFormat="{TemplateBinding ContentStringFormat}"
                        SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                        VerticalAlignment="Center"
                        HorizontalAlignment="Right"
                        />
                </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 {ComponentResourceKey ResourceId=FocusBorderBrushKey, TypeInTargetAssembly={x:Type DataGrid}}}"/>
        </Trigger>
    </Style.Triggers>
</Style>

3

我曾经也遇到过同样的问题,现在已经解决了。如果您想在 c# 代码内部处理此问题,则需要设置一系列的 setter:

DataGridTextColumn numColumn = new DataGridTextColumn
Style s = new Style();
s.Setters.Add(new Setter(HorizontalAlignmentProperty, HorizontalAlignment.Stretch));
s.Setters.Add(new Setter(HorizontalContentAlignmentProperty, HorizontalAlignment.Right));
s.Setters.Add(new Setter(TextBlock.HorizontalAlignmentProperty, HorizontalAlignment.Stretch));
s.Setters.Add(new Setter(TextBlock.TextAlignmentProperty, TextAlignment.Right));
numColumn.CellStyle = s;

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