WPF Datagrid右对齐数字列

时间:2011-07-20 08:23:26

标签: wpf datagrid wpfdatagrid

我正在尝试为我的应用程序中的DataGrid单元格创建样式。我知道可能有一种方法可以使用DataTrigger在DataGrid中对齐数字单元格。这甚至可能吗?

我的DataGrid风格是:

<Style TargetType="{x:Type DataGrid}">
    <Setter Property="AlternatingRowBackground">
        <Setter.Value>
            <SolidColorBrush Color="#CCCCCC" />
        </Setter.Value>
    </Setter>
    <Setter Property="CanUserAddRows" Value="False" />
    <Setter Property="CanUserDeleteRows" Value="False" />
    <Setter Property="Background">
        <Setter.Value>
            <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
                <GradientStop Offset="0" Color="#CCCCCC" />
                <GradientStop Offset="1" Color="#FFFFFF" />
            </LinearGradientBrush>
        </Setter.Value>
    </Setter>
    <Setter Property="RowHeaderWidth" Value="0" />
    <Setter Property="CellStyle">
        <Setter.Value>
            <Style TargetType="{x:Type DataGridCell}">
                <Style.Triggers>
                    <Trigger Property="IsSelected" Value="True">
                        <Setter Property="Background">
                            <Setter.Value>
                                <SolidColorBrush Color="#7777FF" />
                            </Setter.Value>
                        </Setter>
                    </Trigger>
                </Style.Triggers>
            </Style>
        </Setter.Value>
    </Setter>
</Style>

我正在考虑在CellStyle上添加某种触发器来检测内容是否为数字(int,double,decimal,...)并相应地设置单元格的样式。这可能吗?

更新

考虑到这一点,我尝试了几件事,但它没有用。我尝试使用定义为:

的DataTrigger
<DataTrigger Binding="{Binding Converter={StaticResource IsNumericConverter}}" Value="True">
    <Setter Property="HorizontalContentAlignment" Value="Right" />
</DataTrigger>

IsNumericConverter的位置:

public class IsNumericConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value is int || (value is decimal || value is double);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return null;
    }
}

但是当我在转换器上设置断点时,我得到的值是整行的类型,而不是每个单独的单元格......

3 个答案:

答案 0 :(得分:1)

执行此操作的一种方法是在代码隐藏中设置触发器。以下方法将触发器应用于DataGridColumn。此触发器使用您的IsNumericConverter来确定是否进行右对齐:

    public static void AddTriggerToColumnStyle(DataGridColumn column)
    {
        var boundColumn = column as DataGridBoundColumn;
        if (boundColumn != null && boundColumn.Binding is Binding)
        {
            string bindingPropertyPath = (boundColumn.Binding as Binding).Path.Path;
            column.CellStyle = new Style()
            {
                BasedOn = column.CellStyle,
                TargetType = typeof(DataGridCell),
                Triggers =
                {
                    new DataTrigger
                    {
                        Binding = new Binding(bindingPropertyPath) { Converter = new IsNumericConverter() },
                        Value = true,
                        Setters =
                        {
                            new Setter
                            {
                                Property = TextBlock.TextAlignmentProperty,
                                Value = TextAlignment.Right
                            }
                        }
                    }
                }
            };
        }
    }

在代码隐藏的构造函数中InitializeComponent()之后调用此方法应该是安全的。

如果列包含数字和非数字数据的混合,则此方法将起作用。如果列仅包含一种类型的数据,则此方法仍然有效,但创建的触发器将永远不会触发或永久触发。

当然,对于使用DataGrids的每个控件,不必在代码隐藏中重复上述方法。您可以将其移动到静态实用程序类,并让所有代码隐藏类调用此方法。您甚至可以添加一个静态实用程序方法,该方法遍历传递它的DataGrid中的列,并为每列调用上述方法。

UPDATE :我修改了上面的方法,允许它推断出绑定属性路径。这使它更容易使用。我还创建了方法publicstatic,以便可以将其移动到静态实用程序类。

我确实想到了另一种方法,它将遍历DataGrid中的所有列,检查绑定,推断绑定的属性类型并将右对齐应用于列。这将避免创建永远不会触发或永久触发的触发器,并且可能适合每个列仅包含一种类型的数据的情况。但是,这种方法仍然需要代码隐藏,它需要传递每行绑定的类型,如果绑定属性路径涉及的不仅仅是单个属性名称,那么会变得复杂。

我担心我无法看到只使用Style的问题的解决方案,并避免代码隐藏。

答案 1 :(得分:1)

我知道这已经有三年了,但我能够完成这项工作而无需向代码隐藏添加任何代码,我想我会分享如何。将此文章用作模型:link

它使用多重绑定来解决将行传递到转换器的原始问题。

将此添加到您的数据网格:

CellStyle="{StaticResource CellRightAlignStyle }"

然后将此样式添加到xaml中,您必须将其添加为资源:

<Window.Resources>

    <Style x:Key="CellRightAlignStyle" TargetType="{x:Type DataGridCell}">
        <Setter Property="HorizontalAlignment">
            <Setter.Value>
                <MultiBinding
                    Converter="{converters:IsNumericConverter}" >
                    <MultiBinding.Bindings>
                        <Binding RelativeSource="{RelativeSource Self}"/>
                        <Binding Path="Row" Mode="OneWay"/>
                    </MultiBinding.Bindings>
                </MultiBinding>
            </Setter.Value>
        </Setter>
    </Style>

</Window.Resources>

然后是转换器:

    public object Convert(
        object[] values,
        Type targetType,
        object parameter,
        CultureInfo culture)
    {
    if (values[1] is DataRow)
        {
            //change the text alignment left or right.
            var cell = (DataGridCell)values[0];
            var row = (DataRow)values[1];
            var columnName = cell.Column.SortMemberPath;

            if (row[columnName] is int || (row[columnName] is decimal ||   row[columnName] is double))
            return System.Windows.HorizontalAlignment.Right;
        }
    return System.Windows.HorizontalAlignment.Left;
    }

    public override object ConvertBack(
        object value,
        Type targetType,
        object parameter,
        CultureInfo culture)
    {
        return null;
    }

现在所有包含数字数据的单元格应正确对齐!

答案 2 :(得分:0)

我使用转换器创建固定长度的字符串和等宽字体以供查看。

转换器:

class TestUser
  include UserDecorator

  def created_at
    Time.new(2019, 7, 2, 11, 53)
  end

  def confirmed_at
    Time.new(2019, 7, 2, 11, 53)
  end
end

u = TestUser.new
u.created_at_datetime
#=> "2019/07/02 11:53:00"

u.confirmed_at_datetime
#=> "Tuesday 2, 2019"

查看:

import { Component } from '@angular/core';

import { HeroService } from './hero.service';

@Component({
  selector: 'my-heroes',
  providers: [HeroService],
  template: `
  `
})
export class HeroesComponent { }

结果:

Result