Reputation: 41983
To put it simply, I have this within a ControlTemplate.Triggers
condition EnterAction
:
<ColorAnimation To="#fe7" Storyboard.TargetProperty="Background.Color" Duration="00:00:00.1" Storyboard.TargetName="brd"/>
But I want the 'to' colour (#fe7
) to be customisable. This is a control derived from ListBox
. I can create a DependencyProperty
, but of course, I cannot bind the To
property of the ColorAnimation
to it because the Storyboard
has to be frozen and you can't freeze something with bindings (as I understand it).
I tried using a {StaticResource}
within the To
, then populating the resource in the code-behind when the DependencyProperty
was changed, by setting this.Resources["ItemColour"] = newValue;
for instance. That didn't work perhaps obviously, it's a static resource after all: no new property values were picked up. DynamicResource
gave the same problem relating to inability to freeze.
The property is only set once when the control is created, I don't have to worry about it changing mid-animation.
Is there a nice way of doing this? Do I have to resort to looking for property changes myself, dynamically invoking and managing storyboards at that point? Or overlaying two versions of the control, start and end colour, and animating Opacity instead? Both seem ludicrous..
Upvotes: 1
Views: 816
Reputation: 16900
Kieren,
Will this serve your purpose?
I have extended the Grid class called CustomGrid and created a TestProperty whose value when changed will change the background color of Grid:
public class CustomGrid : Grid
{
public bool Test
{
get
{
return (bool)GetValue(TestProperty);
}
set
{
SetValue(TestProperty, value);
}
}
public static readonly DependencyProperty TestProperty =
DependencyProperty.Register("Test", typeof(bool), typeof(CustomGrid),
new PropertyMetadata(new PropertyChangedCallback
((obj, propChanged) =>
{
CustomGrid control = obj as CustomGrid;
if (control != null)
{
Storyboard sb = new Storyboard() { Duration = new Duration(TimeSpan.FromMilliseconds(500)) };
Random rand = new Random();
Color col = new Color()
{
A = 100,
R = (byte)(rand.Next() % 255),
G = (byte)(rand.Next() % 255),
B = (byte)(rand.Next() % 255)
};
ColorAnimation colAnim = new ColorAnimation();
colAnim.To = col;
colAnim.Duration = new Duration(TimeSpan.FromMilliseconds(500));
sb.Children.Add(colAnim);
Storyboard.SetTarget(colAnim, control);
Storyboard.SetTargetProperty(colAnim, new PropertyPath("(Panel.Background).(SolidColorBrush.Color)"));
sb.Begin();
}
}
)));
}
This is the button click event that changes the color:
private void btnClick_Click(object sender, RoutedEventArgs e)
{
gridCustom.Test = (gridCustom.Test == true) ? false : true;
}
I am changing the background color of Grid because I don't have your Listbox.
Finally this is the xaml:
<Grid x:Name="grid" Background="White">
<local:CustomGrid x:Name="gridCustom" Background="Pink" Height="100" Margin="104,109,112,102" >
</local:CustomGrid>
<Button Content="Click Me" x:Name="btnClick" Height="45" HorizontalAlignment="Left" Margin="104,12,0,0" VerticalAlignment="Top" Width="145" Click="btnClick_Click" />
</Grid>
Will this serve your purpose? Let me know or I misunderstood the question?
EDIT:
See this code:
ColorAnimation's To property cannot be bound as you probably guessed. But that doesn't mean you can't change it's value. You can always get a reference to the ColorAnimation and change it's To value and it will all work out well. So from WPF world of binding we need to change a bit and bind the data how we used to do it in Winforms :). As an example see this:
This is the xaml:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero" x:Class="ControlTemplateTriggers.MainWindow"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Storyboard x:Key="Storyboard">
<ColorAnimation From="Black" To="Red" Duration="00:00:00.500" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)" Storyboard.TargetName="gridCustom" />
</Storyboard>
</Window.Resources>
<Grid x:Name="grid" Background="White">
<Grid x:Name="gridCustom" Background="Pink" Height="100" Margin="104,109,112,102" />
<Button Content="Click Me" x:Name="btnClick" Height="45" HorizontalAlignment="Left" Margin="104,12,0,0" VerticalAlignment="Top" Width="145" Click="btnClick_Click" />
</Grid>
</Window>
This is the code behind:
using System.Windows;
using System.Windows.Media.Animation;
using System.Windows.Media;
using System;
namespace Sample {
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
}
private void btnClick_Click(object sender, RoutedEventArgs e)
{
Storyboard sb = this.Resources["Storyboard"] as Storyboard;
if (sb != null)
{
ColorAnimation frame = sb.Children[0] as ColorAnimation;
Random rand = new Random();
Color col = new Color()
{
A = 100,
R = (byte)(rand.Next() % 255),
G = (byte)(rand.Next() % 255),
B = (byte)(rand.Next() % 255)
};
frame.To = col;
sb.Begin();
}
}
}
}
As you can see I am getting a reference to the storyboard and changing it's To property. Your approach to StaticResource obviously wouldn't work. Now what you can do is, in your DependencyProperty
callback somehow get a reference to the Timeline that you want to animate and using VisualTreeHelper or something and then set it's To
property.
This is your best bet.
Let me know if this solved your issue :)
Upvotes: 2
Reputation: 1542
Surely not.. What i understood is that u want color A on the Condition A and Color B on some other condition B....so if there's a property with multiple options u can put datatriggers for those condition only...like if Job done = Red, Half done = Green like wise.. If i misunderstood the problem please correct me..
I think i got ur question ...UR control is user configurable so what ever user select , control's background needs to be set to that color with animation right?
Upvotes: 0
Reputation: 1542
can u put multiple DataTriggers with each having respective color for the "To" property...
Upvotes: 0