5

我一直在寻找我希望这个问题的一个非常简单的解决方案,但是虽然我在 stackoverflow 上发现了很多其他问题,这些问题似乎提出了类似的问题,并提供了一些建议的答案,但我已经通过它们全部,答案要么不起作用,要么实际上并没有回答问题。

我有一个带有几列的 WPF DataGrid,我已将其设置为 DataGridTemplateColumns,如下所示:

<DataGridTemplateColumn Header="Price 1" Width="60">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <ContentPresenter Content="{Binding Price1}" ContentTemplate="{StaticResource NumericCellDataTemplate}" />
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

<DataGridTemplateColumn Header="Price 2" Width="60">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <ContentPresenter Content="{Binding Price2}" ContentTemplate="{StaticResource NumericCellDataTemplate}" />
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

<DataGridTemplateColumn Header="Price 3" Width="60">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <ContentPresenter Content="{Binding Price3}" ContentTemplate="{StaticResource NumericCellDataTemplate}" />
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

我已经定义了一个名为“NumericCellDataTemplate”的可重复使用的 DataTemplate,它为每一列提供了一些共同的特性,包括数字格式、对齐和值变化的背景突出显示。请注意,这一切都源于我在 ViewModel 中定义的一些特殊属性:

<DataTemplate x:Key="NumericCellDataTemplate">
    <Border Name="cellBorder" BorderThickness="0" BorderBrush="Transparent">
        <Border.Style>
            <Style TargetType="{x:Type Border}">
                <Style.Setters>
                    <Setter Property="Background" Value="Transparent" />
                </Style.Setters>
                <Style.Triggers>
                    <DataTrigger Binding="{Binding IsRecentlyChanged}" Value="True">
                        <DataTrigger.EnterActions>
                            <BeginStoryboard Storyboard="{StaticResource IsRecentlyChangedEnterStoryboard}" />
                        </DataTrigger.EnterActions>
                        <DataTrigger.ExitActions>
                            <BeginStoryboard Storyboard="{StaticResource IsRecentlyChangedExitStoryboard}" />
                        </DataTrigger.ExitActions>
                    </DataTrigger>                                
                </Style.Triggers>
            </Style>
        </Border.Style>
        <TextBlock Text="{Binding Value, StringFormat='#,##0.00'}" HorizontalAlignment="Right" />
    </Border>
</DataTemplate>

我已经为那些背景颜色动画设置了故事板,当值改变时触发。viewModel 正在跟踪这个并分别为每个值设置/取消设置我的 IsRecentlyChanged 属性:

<Storyboard x:Key="IsRecentlyChangedEnterStoryboard">
    <ColorAnimation Duration="0:0:0.3" To="LightSteelBlue" FillBehavior="HoldEnd" Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)" />
</Storyboard>
<Storyboard x:Key="IsRecentlyChangedExitStoryboard">
    <ColorAnimation Duration="0:0:0.3" To="Transparent" FillBehavior="HoldEnd" Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)" />
</Storyboard>

这里的一切似乎都运行良好。请注意,我使用自定义 DataGridTemplateColumn 而不仅仅是简单的 DataGridTextColumn 的原因之一是我绑定到的属性(例如 Price1)是一个复杂对象,而不仅仅是要显示的简单值类型或字符串. 它实际上是一个 IPropertyModel,它是我定义的一个接口,其中包含一些有用的属性供视图层绑定到:

public interface IPropertyModel : INotifyPropertyChanged
{
    string Name { get; }
    bool IsRecentlyChanged { get; }
}

public interface IPropertyModel<T> : IPropertyModel
{
    T Value { get; set; }
}

所以我想做的就是找到一种方法来将我上面提到的那些 DataGridTemplateColumns 的定义简化为一个简单的单行内容,如下所示:

<DataGridTemplateColumn Header="Price1" Width="60" Binding="{Binding Price1}" ContentTemplate="{StaticResource NumericCellDataTemplate}" />

当然,这里的问题是 DataGridTemplateColumn 没有 DataGridTextColumn 那样的 Binding 属性。我已经尝试了许多建议,例如在 DataGridCell 上使用 Style 以使用新的 ControlTemplate 完全覆盖其模板,并提供自定义 ContentPresenter。我还尝试使用 DataGridTextColumn 执行此操作,以利用它已经具有我们可以使用的 Binding 属性这一事实 - 但我看不到如何从 Style 或 ContentPresenter 中访问它。

一些建议谈到使用 RelativeAncestor 或 TemplateBinding 返回 DataGridTemplateColumn,然后从中读取附加属性,例如 ap:MyAttachedProperties.Binding - 但正如一些人所指出的,一旦您在 DataGridCell 模板中,您不再可以访问原始的 DataGridTemplateColumn,因为我猜它不在 Visual/Logical 树中?因此,经过大量实验,也没有证明有帮助。

任何其他建议将不胜感激。如果有人有更好的主意,我很乐意使用 DataGridTextColumn、DataGridTemplateColumn 或其他东西。在此示例中,我只有 3 列,以及所有这些列的一个可重复使用的 DataTemplate。但是想象一个更复杂的场景,我们有 20 多列,可能绑定到几个不同的可重用 DataTemplate 中的一个来执行不同类型的格式化和显示逻辑 - 所以如果每一列都需要 7 多行 XAML 代码,这将变得一团糟.

谢谢!

4

0 回答 0