Как запустить анимацию при изменении значения метки в WPF?

Извиняюсь за этот тривиальный вопрос, я новичок в WPF и продолжаю находить блоги, которые почти описывают то, что я хочу...

У меня есть метка, которая привязана к свойству и хорошо обновляется на экране, и теперь мне нужна небольшая анимация, которая мигает фоновым цветом метки всякий раз, когда значение обновляется. В идеале я хотел бы чистое решение xaml

Я просмотрел DataTriggers, но они, похоже, требуют соблюдения условия равенства, а EventTriggers, похоже, невозможно привязать к каким-либо событиям, связанным с отображением данных.

спасибо Оскар


person Oskar    schedule 29.12.2009    source источник


Ответы (3)


пожалуйста, проверьте, будет ли код ниже работать для вас. Любое изменение свойства Content этикетки анимируется. Это делается с использованием триггеров и класса преобразователя значений, который выполняет небольшой трюк, преобразуя значение содержимого в «Истина» или «Ложь», и триггеры настроены на реакцию на эти два значения. Преобразователь прикрепляется к свойству Tag метки, которая согнута к свойству Name контекста данных. Также я добавил некоторую анимацию для событий входа и выхода мыши, которые довольно просты и выполняются только с использованием RouterEvents в xaml.

преобразователь:

public class TestConverter : IValueConverter
{
    private string  _originalValue = String.Empty;
    private bool    _previousValue = false;

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        _originalValue = (string)value;
        _previousValue = !_previousValue;
        return _previousValue.ToString();
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return _originalValue;
    }
}

инициализация контекста данных:

label1.DataContext = new Test() { Name = DateTime.Now.ToString() };

xaml:

<Window.Resources>
    <local:TestConverter x:Key="TestConverter" />
</Window.Resources>
<Grid>
    <Label             
        Height="28" 
        HorizontalAlignment="Left" 
        Margin="132,96,0,0" 
        Name="label1" VerticalAlignment="Top" Width="120">

        <Label.Content>
            <Binding Path="Name"/>
        </Label.Content>
        <Label.Tag>
            <Binding Path="Name" Converter="{StaticResource TestConverter}"/>
        </Label.Tag>
        <Label.Background>
            <SolidColorBrush x:Name="animatedBrush1" Color="Yellow" />
        </Label.Background>
        <Label.Style>
            <Style TargetType="Label">
                <Style.Triggers>
                    <Trigger Property="Tag" Value="True">
                        <Trigger.EnterActions>
                            <BeginStoryboard>
                                <Storyboard AutoReverse="True">
                                    <!--<DoubleAnimation 
                                        Storyboard.TargetProperty="FontSize" To="20"/>-->
                                    <DoubleAnimation 
                                        Storyboard.TargetProperty="Opacity" To="0.0" AutoReverse="True"/>
                                </Storyboard>
                            </BeginStoryboard>
                        </Trigger.EnterActions>
                    </Trigger>
                    <Trigger Property="Tag" Value="False">
                        <Trigger.EnterActions>
                            <BeginStoryboard>
                                <Storyboard AutoReverse="True">
                                    <DoubleAnimation 
                                        Storyboard.TargetProperty="FontSize" To="20"/>
                                    <!--"<DoubleAnimation 
                                        Storyboard.TargetProperty="Opacity" To="0.0" AutoReverse="True"/>-->
                                </Storyboard>
                            </BeginStoryboard>
                        </Trigger.EnterActions>
                    </Trigger>
                </Style.Triggers>
            </Style>
        </Label.Style>
        <Label.Triggers>
            <EventTrigger RoutedEvent="Label.MouseEnter">
                <BeginStoryboard>
                    <Storyboard>
                        <ColorAnimation
                            Storyboard.TargetName="animatedBrush1"
                            Storyboard.TargetProperty="Color"
                            To="Blue" Duration="0:0:1" />
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
            <EventTrigger RoutedEvent="Label.MouseLeave">
                <BeginStoryboard>
                    <Storyboard>
                        <ColorAnimation
                            Storyboard.TargetName="animatedBrush1"
                            Storyboard.TargetProperty="Color"
                            To="Yellow" Duration="0:0:1" />
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
        </Label.Triggers>
    </Label>
</Grid>

надеюсь, это поможет, с уважением

person serge_gubenko    schedule 30.12.2009
comment
У меня возникли проблемы с изменением анимации на ColorAnimation, свойство Background.Color недействительно: не удается разрешить все ссылки на свойства в пути к свойству «Background.Color». Убедитесь, что применимые объекты поддерживают свойства. Почему это хорошо работает в ваших триггерах событий, но не в триггере стиля? спасибо Оскар - person Oskar; 30.12.2009
comment
хорошо, наконец получил это. Проблема заключалась в том, что свойство Background не было присвоено метке (и каким-то образом не унаследовано), поэтому было нулевым. Установка его явно на метке работает нормально, а установка его на сетке, в которой находится метка, не работает. - person Oskar; 30.12.2009
comment
Пожалуйста, предоставьте немного больше информации о том, что вы пытаетесь сделать; может быть, создать новый вопрос, в котором часть вашего кода не работает, чтобы я мог посмотреть на него, спасибо - person serge_gubenko; 30.12.2009

Разве вы не должны использовать триггер события? Вам нужно установить NotifyOnTargetUpdated=True в привязке, но это работает в моем коде.

<DataTemplate>
    <Border Name="templateBorder">
        <TextBlock Text="{Binding Path=Name, NotifyOnTargetUpdated=True}" />
    </Border>
    <DataTemplate.Triggers>
        <EventTrigger RoutedEvent="Binding.TargetUpdated">
            <BeginStoryboard>
                <Storyboard AutoReverse="True">
                    <DoubleAnimation Storyboard.TargetProperty="Opacity" 
                                     To=".1" Duration="0:0:.5" />
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </DataTemplate.Triggers>
</DataTemplate>
person Luk    schedule 27.01.2012
comment
Не могу заставить это работать... Я использую то же самое с меткой... в триггере события не появляется, что RoutedEvent=Binding.Targetupdated запускается... Мне ничего не нужно в код для этого я? - person MattE; 28.02.2019
comment
Пришлось изменить привязку в TextBloxk на {Binding Path=DataContext.Name}, чтобы она заработала. - person MattE; 01.03.2019

Мне понравился ответ serge_gubenko, но я подумал, что должен упомянуть еще одну технику, которую я иногда использую. Ответ Сержа ближе к вашему идеалу "чистого XAML", потому что в нем есть только конвертер, но в этом ответе меньше кода и он может быть более читаемым. Вот:

Добавьте PropertyChangedCallback к свойству «Name» и запустите раскадровку оттуда:

DependencyProperty NameProperty = DependencyProperty.Register( ..., new UIElementMetadata
{
  PropertyChangedCallback = (obj, e) =>
  {
    storyBoard.Begin();
  }
});

Если вам не нужна вспышка при первой загрузке окна, вы можете добавить флаг:

...
  PropertyChangedCallback = (obj, e) =>
  {
    if(_initialized)
      storyBoard.Begin();
  }
...

protected override void OnInitialized(...)
{
  _initialized = true;
}
person Ray Burns    schedule 30.12.2009