1

我有一个DataGrid代表我正在执行 ping 的主机的行和一个名为的列Lost,它代表丢失的 ICMP 数据包,随着时间的推移价值增加。我把整个INotifyPropertyChanged事情都搞砸了,我看到价值增加了​​。我想要做的是编写一个相对于列的值Style逐渐将行的背景颜色从白色更改为深红色的内容。Lost

如果可能的话,我想编写一个TriggerDataTrigger设置为 a 的 setter 值来ValueConverter计算所需的颜色,但到目前为止,我一直未能成功编写一种样式,该样式将在每次丢失单元格的值更改时更新。当我加载新的数据上下文并切换回来(仅用于测试)时,我只会看到颜色的差异。

这是我尝试过的:

    <Style x:Key="DownStyle" TargetType="{x:Type DataGridRow}">
        <Setter Property="Background" Value="{Binding Converter={StaticResource BackgroundConverter}}" />
    </Style>

我看不到这与 a 一起工作,DataTrigger因为无论如何您都必须指定一个值,并且这些值是无限的(或者我猜是 Int32.MaxValue),真的。尽管我也尝试为 value 属性指定 a 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实际绑定到将要发生变化的东西(在这种情况下,我觉得我也被迫使用 aValueConverter来获取列的值,有没有更直接的方法?),但即使我这样做了,我将什么指定为DataTrigger's 值?

编辑: 所以就我而言,我继续执行以下操作(目前这只会修改TextBlock's 背景):

<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. 无论如何,对于如此简单的事情来说,这一切似乎都非常冗长,所以我继续使用代码隐藏路线。

4

2 回答 2

1

您在转换器的正确轨道上。您使用的技术有时称为“分箱”,它将一大组整数映射到一组固定的小值。它还用于创建直方图。

至于不更新,您的绑定表达式必须更具体地检索属性,否则在更改Lost时不会重新评估它。Lost更改后,您还需要更新转换器。

于 2011-04-22T01:21:43.760 回答
1

我想 Triggers 和 DataTriggers 在这种情况下无济于事,因为 datagigger 的值不稳定。更糟糕的是,它不是依赖属性,你不能绑定到它。在我看来,更好的方法是使用 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));
        }
    }

}
于 2011-04-22T12:52:55.467 回答