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

发布于 2024-12-10 04:03:59 字数 1520 浏览 0 评论 0原文

我正在使用 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

如果我删除 CellStyle,该区域将按预期工作,但当然我会失去正确的对齐方式。

具有适当宽度的DataGrid单元格

有谁知道如何实现这两个目标?

我尝试过的事情

  1. 将绑定上的 TargetNullValue 设置为具有一定宽度的格式。 这适用于现有行,但对新行没有影响。
  2. 在列上设置 MinWidth,这不会影响新可选行的宽度 区域。

有效的方法:

使用 @AngelWPF 答案中的信息,我能够从使用 CellStyle 更改为使用 ElementStyle,如下

<DataGridTextColumn Binding="{Binding Path=ImpaId}"
                    CellStyle="{StaticResource CellRightAlign}">

所示:

<DataGridTextColumn Binding="{Binding Path=ImpaId}"
                    ElementStyle="{StaticResource CellRightAlign}">

I'm using a WPF4.0 DataGrid. When double clicking on a cell in a new row everything works fine unless I've added a cell style to that column. For example, I have a numeric column where I want the data right aligned so the xaml looks like this

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

Where the style in a shared resource is just:

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

The resulting selectable area on a new row is shown in the image as that small blue area.This is a very small target for the user to hit, and this happens to be the most likely column they will want to start with on a new row.

DataGrid cell with tiny width

If I remove the CellStyle, the area works as desired but of course I lose the right alignment.

DataGrid cell with proper width

Does anyone know how to achieve both?

Things I tried

  1. Setting TargetNullValue on the binding to a format with some width.
    This works on existing rows but has no effect on a new row.
  2. Setting MinWidth on the column, this did not affect the width of the new row selectable
    area.

Thing that worked:

Using the information from the answer by @AngelWPF I was able to change from using CellStyle to using ElementStyle as follows:

<DataGridTextColumn Binding="{Binding Path=ImpaId}"
                    CellStyle="{StaticResource CellRightAlign}">

Became

<DataGridTextColumn Binding="{Binding Path=ImpaId}"
                    ElementStyle="{StaticResource CellRightAlign}">

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

咽泪装欢 2024-12-17 04:04:00

我刚刚遇到了类似的问题,并通过覆盖 Blend 中 DataGridCell 的样式找到了另一个解决方案。

原始样式的更改项是样式本身中用于拉伸单元格本身的 VerticalAlignmentVerticalContentAlignment 的设置器以及 VerticalAlignment="Center"和 Template 属性中的 Horizo​​ntalAlignment="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>

I just had a similar problem and found another solution by overwriting the Style for the DataGridCell in Blend.

The changed items from the original style are the setters for VerticalAlignment and VerticalContentAlignment in the Style itself to stretch the cell itself and VerticalAlignment="Center" and HorizontalAlignment="Right" in the Template property to align the content. Change these values to whatever you need to align the cells content.

The rest of the style could be removed so that the settings from the base style will be used (using the StaticResource the style is BasedOn). However I left the style as Blend produced it.

This resulting XAML-Code should then be included into the controls resources:

<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>
oО清风挽发oО 2024-12-17 04:04:00

我有同样的问题,现在已经解决了。如果你想在 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;

I had the same issue and got it solved now. If you want to do it inside the c# code, you need to set a bunch of setters:

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;
孤檠 2024-12-17 04:03:59

您可以在针对 TextBlockDataGridTextColumn 上应用 ElementStyle 并将其右对齐,这样就可以了。

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

You could apply ElementStyle on the DataGridTextColumn targetted to TextBlock and right align that, it would work.

      <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> 
热情消退 2024-12-17 04:03:59

只是想为将来的代码搜索添加更多示例。

我将其放在 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}"/>

这会右对齐文本并且仍然启用排序。文本框填充单元格,在本例中使用布尔转换器着色。

Just wanted to add to more examples for future code searches.

I put this in the top of the xaml file:

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

And then in the datagrid:

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

This right aligns the text and sorting is still enabled. The textbox fills the cell and in this case is colored using a bool converter.

醉殇 2024-12-17 04:03:59

您可以尝试解决方法:

           <DataGridTemplateColumn>
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <Grid Background="White" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
                        <TextBlock HorizontalAlignment="Right" Text="{Binding Path=ImpaId}"/>
                    </Grid>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>

You can try a work around :

           <DataGridTemplateColumn>
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <Grid Background="White" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
                        <TextBlock HorizontalAlignment="Right" Text="{Binding Path=ImpaId}"/>
                    </Grid>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文