use*_*211 5 c# wpf xaml wpfdatagrid
我一直在寻找我希望对这个问题的解决方案非常简单的方法,但是尽管我在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>
Run Code Online (Sandbox Code Playgroud)
我定义了一个可重用的DataTemplate,称为“ NumericCellDataTemplate”,它为每个列提供了一些通用功能,包括数字格式,对齐方式和值更改时的背景突出显示。请注意,这全部是由我在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>
Run Code Online (Sandbox Code Playgroud)
我已经为这些背景色动画设置了情节提要,当值更改时将触发它们。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>
Run Code Online (Sandbox Code Playgroud)
这里的一切似乎工作正常。请注意,我使用自定义DataGridTemplateColumn而不是简单的DataGridTextColumn的原因之一是,我绑定到的属性(例如Price1)是一个复杂的对象,而不仅仅是要显示的简单值类型或字符串。它实际上是一个IPropertyModel,它是我定义的接口,具有一些有用的属性供视图层绑定到:
public interface IPropertyModel : INotifyPropertyChanged
{
string Name { get; }
bool IsRecentlyChanged { get; }
}
public interface IPropertyModel<T> : IPropertyModel
{
T Value { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
因此,我要做的就是找到一种方法,将上面提到的DataGridTemplateColumns的定义简化为一个简单的单行代码,如下所示:
<DataGridTemplateColumn Header="Price1" Width="60" Binding="{Binding Price1}" ContentTemplate="{StaticResource NumericCellDataTemplate}" />
Run Code Online (Sandbox Code Playgroud)
当然,这里的问题是DataGridTemplateColumn不像DataGridTextColumn那样具有Binding属性。我尝试了许多建议,例如在DataGridCell上使用样式用新的ControlTemplate完全覆盖其Template,并提供自定义ContentPresenter。我还尝试使用DataGridTextColumn进行此操作,以利用它已经具有我们可以使用的Binding属性这一事实,但是我看不到如何从Style或ContentPresenter中访问它。
一些建议涉及使用RelativeAncestor或TemplateBinding返回到DataGridTemplateColumn,然后从中读取一个附加属性,例如ap:MyAttachedProperties.Binding-但正如有些人指出的,一旦进入DataGridCell模板,您便可以不再具有对原始DataGridTemplateColumn的访问权限,因为我认为它不在Visual / Logical树中吗?因此,经过大量实验后,也证明没有帮助。
任何其他建议,将不胜感激。如果有人有更好的主意,我很乐意使用DataGridTextColumn,DataGridTemplateColumn或其他东西。在此示例中,我只有3列,并且所有列都有一个可重用的DataTemplate。但是,想象一下一个更复杂的场景,其中我们有20多个列,可能绑定到几个不同的可重用DataTemplate之一来执行不同类型的格式设置和显示逻辑-因此,如果每列都需要7+行XAML代码,这将变得混乱。
谢谢!