views:

466

answers:

2

Apologies for this trivial question, I'm new to WPF and keep finding blogs that almost describe what I want...

I have a Label that is bound to a property and updating nicely on screen, and now I'd like a small animation that flashes the background colour of the label whenever the value is updated. Ideally I'd like a pure xaml solution

I've looked at DataTriggers but they seem to require an equality condition to hold, and EventTriggers seem to not be possible to attached to any events to do with the display of data

thanks Oskar

+1  A: 

please check if code below would work for you. Any change for Content property of the label is animated. It's done using triggers and value converter class which does the small trick converting content value to either "True" or "False" and triggers are set up to react on those 2 values. Cnverter is attached to the Tag property of the label which is bent to the Name property of data context. Also I've added some animation to mouse enter and leave events which are pretty straightforward and done only using RouterEvents in xaml.

converter:

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;
    }
}

data context initialization:

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>

hope this helps, regards

serge_gubenko
I'm having trouble changing the animation to a ColorAnimation, the property Background.Color isn't valid:Cannot resolve all property references in the property path 'Background.Color'. Verify that applicable objects support the properties.Why does it work nicely in your event triggers but not in the style trigger?thanksOskar
Oskar
ok, finally got this one. The problem was that the Background property wasn't assigned on the Label (and somehow not inherited) so was null. Setting it explicitly on the label works fine, and setting it on the grid the label sits in doesn't
Oskar
pls provide a little more details on what are you trying to do; may be create a new question with some of your code not working so I could look at it, thnx
serge_gubenko
+1  A: 

I liked serge_gubenko's answer but thought I should mention another technique I sometimes use. Serge's answer is closer to your "pure XAML" ideal because it only has a converter, but this answer has less code and may be more readable. Here it is:

Add a PropertyChangedCallback to your "Name" property and start the storyboard from there:

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

If you don't want a flash when the window first loads, you can add a flag:

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

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