我有一个DataGrid
,其中的行代表我正在ping的主机和一个名为Lost
的列,它代表丢失的ICMP数据包随着时间的推移而增加的值。我把整个INotifyPropertyChanged
的东西都弄下了,我看到价值在增加。我想要做的是写一个Style
,它会相对于Lost
列的值逐步将行的背景颜色从白色变为深红色。
如果可能的话,我想写一个Trigger
或DataTrigger
,其设置值设置为ValueConverter
,这将计算所需的颜色,但到目前为止,我写了一个风格,每次丢失的单元格的值发生变化时都会更新,这是不成功的。当我加载新的数据上下文并切换回来时(仅用于测试),我只看到颜色的差异。
这是我尝试过的:
<Style x:Key="DownStyle" TargetType="{x:Type DataGridRow}">
<Setter Property="Background" Value="{Binding Converter={StaticResource BackgroundConverter}}" />
</Style>
我无法看到这与DataTrigger
一起工作,因为你必须指定一个值,而且值是无限的(或者我猜的是Int32.MaxValue)。虽然我也尝试为value属性指定ValueConverter
,但也不起作用。
修改 瑞克:我曾经尝试过这样的事情:
<Style x:Key="DownStyle" TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<DataTrigger Binding="{Binding Converter={StaticResource LostColumnValueConverter}}" Value="Somenumber">
<Setter Property="Background" Value="{Binding Converter={StaticResource BackgroundConverter}}" />
</DataTrigger>
</Style.Triggers>
</Style>
我想我理解需要让Trigger
实际绑定到将会发生变化的事情(在这种情况下,我觉得我也被迫使用ValueConverter
来获取列的值,有更直接的方法吗?),但即使我这样做,我还应该指定DataTrigger
的值?
修改
所以在我的情况下,我继续做了以下事情(目前这只会修改TextBlock
的背景):
<DataGridTemplateColumn Header="Lost" Width="Auto">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Lost, NotifyOnTargetUpdated=True}">
<TextBlock.Triggers>
<EventTrigger RoutedEvent="Binding.TargetUpdated">
<BeginStoryboard>
<Storyboard>
<ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{Binding Converter={StaticResource BackgroundConverter}}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</TextBlock.Triggers>
</TextBlock>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
对我来说似乎是正确的,但由于某种原因只能运作一次。我在TargetUpdated
定义上添加了一个单独的TextBlock
事件处理程序,以查看是否确实在每次更改时都调用了该事件。
我EventTrigger
上必须遗漏一些东西。可能与Storyboard
有关。
无论如何,对于这么简单的事情来说,这一切似乎都非常冗长,所以我继续使用代码隐藏路线。
答案 0 :(得分:1)
您使用转换器正确。您正在使用的技术有时称为“binning”,它将大量整数映射到固定的一组小值。它也用于创建直方图。
就未更新而言,绑定表达式必须更具体,才能检索Lost
属性,否则在Lost
更改时不会重新评估它。更改后,您还需要更新转换器。
答案 1 :(得分:1)
我认为Triggers和DataTriggers在这种情况下无法提供帮助,因为datagrigger的值不稳定。更糟糕的是,它不是依赖属性,你无法绑定它。在我看来,更好的方法是使用EventTrigger。
<Window.Resources>
<BeginStoryboard x:Key="bsbPing">
<Storyboard>
<DoubleAnimation Duration="0:0:0.2" Storyboard.TargetProperty="FontSize" To="{Binding Path=PingValue}" />
</Storyboard>
</BeginStoryboard>
</Window.Resources>
<Grid>
<StackPanel>
<TextBox Name="txbPingValue" Text="{Binding Path=PingValue}">
<TextBox.Triggers>
<EventTrigger RoutedEvent="TextBox.TextChanged">
<EventTrigger.Actions>
<StaticResource ResourceKey="bsbPing" />
</EventTrigger.Actions>
</EventTrigger>
</TextBox.Triggers>
</TextBox>
<Button Name="btnPing" Click="btnPing_Click">Ping</Button>
</StackPanel>
</Grid>
和代码:
public partial class Window7 : Window
{
public Ping MyPing { get; set; }
public Window7()
{
InitializeComponent();
MyPing = new Ping { PingValue = 20.0 };
this.DataContext = MyPing;
}
private void btnPing_Click(object sender, RoutedEventArgs e)
{
MyPing.PingValue += 10;
}
}
public class Ping : INotifyPropertyChanged
{
private double pingValue;
public double PingValue
{
get
{
return pingValue;
}
set
{
pingValue = value;
NotifyPropertyChanged("PingValue");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}