如何在DataGrid中为DataGridTemplateColumn创建可重用的CellTemplate? (仅限XAML)

时间:2012-08-14 14:59:27

标签: c# wpf xaml wpfdatagrid

我一直在寻找我希望应该是这个问题的一个非常简单的解决方案,但是虽然我已经发现了很多关于stackoverflow的其他问题似乎问了类似的问题,并提出了一些建议的答案,我和#39;已经完成了所有这些,答案要么不起作用,要么实际上没有回答这个问题。

我有一个带有几列的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>

我已经定义了一个名为&#34; NumericCellDataTemplate&#34;的可重用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中访问它。 / p>

一些建议谈到使用RelativeAncestor或TemplateBinding来返回DataGridTemplateColumn,然后从中读取附加属性,例如ap:MyAttachedProperties.Binding - 但有些人已经注意到,一旦你在DataGridCell中模板,你不再有权访问原始DataGridTemplateColumn,因为它不在Visual / Logical树中我猜?经过多次实验,这也没有证明有用。

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

谢谢!

0 个答案:

没有答案