Обновление стиля wpf с бесконечными возможными условиями - PullRequest
1 голос
/ 22 апреля 2011

У меня есть DataGrid со строками, представляющими хост, с которым я выполняю эхо-запросы, и столбец с именем Lost, который представляет потерянные ICMP-пакеты, значение которых со временем увеличивается.У меня есть целая вещь INotifyPropertyChanged, и я вижу увеличение стоимости.Я хочу написать Style, который изменит цвет фона строки с белого на темно-красный постепенно относительно значения столбца Lost.

Я бы хотел, если бы это было возможно,напишите Trigger или DataTrigger с установочным значением, равным ValueConverter, которое будет вычислять необходимый цвет, но до сих пор мне не удалось написать стиль, который будет обновляться каждый раз, когда изменяется значение ячейки Lost.Я вижу разницу в цвете только когда загружаю новый контекст данных и переключаюсь обратно (только для тестирования).

Вот что я пробовал:

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

Я не вижуэто работает с DataTrigger, так как вы должны в любом случае указать значение, а значения бесконечны (или, я думаю, Int32.MaxValue).Хотя я также попытался указать ValueConverter для свойства value, но это тоже не сработало.

Кстати, я хочу по возможности избежать кодового отступа.

Редактировать: Рик: Я пытался сделать что-то вроде:

    <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.В любом случае, все это кажется невероятно многословным для чего-то такого простого, поэтому я пошел дальше и выбрал маршрут с выделенным кодом.

Ответы [ 2 ]

1 голос
/ 22 апреля 2011

Полагаю, триггеры и 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));
        }
    }

}
1 голос
/ 22 апреля 2011

Вы на правильном пути с конвертером.Технику, которую вы используете, иногда называют «binning», которая отображает большой набор целых чисел в фиксированный небольшой набор значений.Он также используется для создания гистограмм.

Если вы не обновляете, ваше выражение привязки должно быть более конкретным для получения свойства Lost, иначе оно не будет переоцениваться при изменении Lost,Как только вы измените его, вам также потребуется обновить конвертер.

...