我正在尝试为我的应用程序中的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;
}
}
但是当我在转换器上设置断点时,我得到的值是整行的类型,而不是每个单独的单元格......
答案 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 :我修改了上面的方法,允许它推断出绑定属性路径。这使它更容易使用。我还创建了方法public
和static
,以便可以将其移动到静态实用程序类。
我确实想到了另一种方法,它将遍历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 { }
结果: