Fire a trigger when Label Content changes

2019-08-27 17:35发布

问题:

I've just started to learn WPF and now I'm doing my second WPF application with C# and .NET Framework 4.7.

I want to fire an animation when Label's Content changes. I have 81 labels on my View and I want to associate the same animation to all of them.

This is one of my labels, but all of them are mostly identical:

<Label x:Name="c00" Content="{Binding BestIndividual[0]}" Margin="0" BorderThickness="2,2,0,0" BorderBrush="Black" />

Searching, I have found this solution, but I don't know how to applied to what I need.

I think I have found how to do it in this article: How to: Trigger an Animation When a Property Value Changes.

But, who can I fire a trigger when Label's Content change?

The only way that I've found about how to fire a trigger is when a property has a value:

<Trigger Property="IsMouseOver" Value="True">

回答1:

EventTriggers are meant for executing actions - animation included - in response to a routed event.

As mm8 suggested, the Label control has no "ContentChanged" event. But instead of using a normal event, you can implement a routed one:

public class CustomLabel : Label
{
    public static readonly RoutedEvent ContentChangedEvent = EventManager.RegisterRoutedEvent(
        "ContentChanged", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(CustomLabel));

    public event RoutedEventHandler ContentChanged
    {
        add
        {
            AddHandler(ContentChangedEvent, value);
        }
        remove
        {
            RemoveHandler(ContentChangedEvent, value);
        }
    }

    protected override void OnContentChanged(object oldContent, object newContent)
    {
        base.OnContentChanged(oldContent, newContent);

        RaiseEvent(new RoutedEventArgs(ContentChangedEvent));
    }
}

In this way you can create a Style with an EventTrigger for beginning an animation:

<Style x:Key="ContentChangedAnimated" TargetType="{x:Type local:CustomLabel}"
        BasedOn="{StaticResource {x:Type Label}}">
    <Style.Triggers>
        <EventTrigger RoutedEvent="ContentChanged">
            <EventTrigger.Actions>
                <BeginStoryboard>
                    <Storyboard>
                        <DoubleAnimation Duration="0:0:2" Storyboard.TargetProperty="FontSize" 
                                            To="28" AutoReverse="True" />
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger.Actions>
        </EventTrigger>
    </Style.Triggers>
</Style>

Then you need to apply that style to your (Custom)Labels:

<local:CustomLabel x:Name="c00" Content="{Binding BestIndividual[0]}" Margin="0" Style="{StaticResource ContentChangedAnimated}"
        BorderThickness="2,2,0,0" BorderBrush="Black" />

I hope it can help you.



回答2:

The Label class has no "ContentChanged" event but you could define your own custom Label class and override the OnContentChanged method:

public class CustomLabel : Label
{
    public event EventHandler ContentChanged;

    protected override void OnContentChanged(object oldContent, object newContent)
    {
        base.OnContentChanged(oldContent, newContent);

        if (ContentChanged != null)
            ContentChanged(this, EventArgs.Empty);
    }
}

In the XAML you replace all Label elements with your custom type:

<local:CustomLabel x:Name="c00" Content="{Binding BestIndividual[0]}" ContentChanged="OnContentChanged" />

You could then perform the animation programmatically in the event handler.



标签: c# wpf animation