Using dynamic parameters for binding ElementName in styles. Reusing styles - c#

I have a question.
I have created a style in WPF designer (XML) for TextBlocks. After IsMouseOver event is fired on any of two image controls, my textBlocks changes its positions. This style is used for some textBlocks.
<Style x:Key="movingTextBlocksStyle" TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=image1, Path=IsMouseOver}" Value="True">
<Setter Property="RenderTransform">
<Setter.Value>
<TranslateTransform/>
</Setter.Value>
</Setter>
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)" From="0" To="-125"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=image2, Path=IsMouseOver}" Value="True">
<Setter Property="RenderTransform">
<Setter.Value>
<TranslateTransform/>
</Setter.Value>
</Setter>
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)" From="0" To="-125"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
This style will be used as:
<TextBlock x:Name="textBlock1" Style="{StaticResource movingTextBlocksStyle}"/>
<TextBlock x:Name="textBlock2" Style="{StaticResource movingTextBlocksStyle}"/>
My problem is that I want to reuse this style for another textBlocks: textBlock3 and textBlock4 where "Binding ElementName" differs, for example image3 and image4.
I have thought that if there was any possibility to reuse this style with some type of dynamic parameter or argument, it would be great.
I searched for any solution only as xml-code without any C# (I am using C# with WPF) or converter implementation.
Thanks in advance.

Here's pure XAML solution:
Collect all controls on which the text block depends in an array and set it as data context:
<Image x:Name="image1"/>
<Image x:Name="image2"/>
<TextBlock Style="{StaticResource movingTextBlocksStyle}">
<TextBlock.DataContext>
<x:Array Type="system:Object">
<x:Reference>image1</x:Reference>
<x:Reference>image2</x:Reference>
</x:Array>
</TextBlock.DataContext>
</TextBlock>
You'll need to remember to change all bindings on the TextBlock properties accordingly, because data context is no longer inherited. Then in the style definition bind using corresponding array indices:
<DataTrigger Binding="{Binding [0].IsMouseOver}" Value="True">...</DataTrigger>
...
<DataTrigger Binding="{Binding [1].IsMouseOver}" Value="True">...</DataTrigger>
The system: prefix namespace is clr-namespace:System;assembly=mscorlib.

You could define attached properties which would hold the controls on which the TextBox depends, like so (I'll use only one property to keep it brief):
static class Helper
{
public static object GetImage(DependencyObject obj)
{
return (object)obj.GetValue(ImageProperty);
}
public static void SetImage(DependencyObject obj, object value)
{
obj.SetValue(ImageProperty, value);
}
public static readonly DependencyProperty ImageProperty =
DependencyProperty.RegisterAttached(
"Image",
typeof(object),
typeof(Helper),
new PropertyMetadata(null));
}
Then, in the data trigger, bind using the attached property:
...
<DataTrigger Binding="{Binding Path=(local:Helper.Image).IsMouseOver, RelativeSource={RelativeSource Self}}" Value="True">
...
Lastly, set the property value to be the control on which the TextBlock depends:
<Image x:Name="image1"/>
...
<TextBlock local:Helper.Image="{Binding ElementName=image1}"
Style="{StaticResource movingTextBlocksStyle}"/>
This solution is not pure XAML - it requires a little bit of code-behind to define the attached properties, but I doubt there's an elegant way to completely avoid it.

Related

WPF: K.O. Can't Synchronize StoryBoards animations + Can't change application theme 😔

So I have a StackPanel menu which has a lot of buttons, each button must have a grid and inside 2 labels, the first for the icon, and the second for a small rectangle which indicates if this button is active or no. In addition, each button is linked to a page, and when the user clicks, the program displays the appropriate page.
When the program wants to get the user's attention to a specific page (for example, a notification page), an animation is started, in which we will flash the icon label (linked to that specific page) 2 times in red color for a short time, and it will be repeated every 10 seconds until the user clicks this button to see the notification.
Problem N: 1
It may happen that multiple notifications arrive at the same time from different pages, in this scenario we need to sync the StoryBoards so that the buttons will flash together every 10 seconds, otherwise you will see an unhappy result as each button will flash separately on others. My first thought was to bind something to the BeginTime of the StoryBoard, and make the StoryBoard wait for the running animations before starting. So, I jumped to the code, and as soon as I write this binding, an awesome exception pops up: Could not freeze this Storyboard timeline tree for use in feeds, I google it and I have found that I am not allowed to use any binding or dynamic resource inside the StoryBoard ControlTemplate, so, I implement a small DependencyProperty in order to synchronize the animation, and this is the reason for which you'll notice this little line here:
<Condition Binding="{Binding Synchronizer}" Value="1"/>
C# Code
public partial class Layout : Window {
public double Synchronizer { get; set; } = 0;
public static readonly DependencyProperty DependencyProperty = DependencyProperty.Register("Synchronizer", typeof(double), typeof(Layout), new PropertyMetadata());
public Layout(){
{
InitializeComponent(); DataContext = this;
}
}
}
This Synchronizer is triggered due to this XAML Code:
<Window.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard>
<Storyboard RepeatBehavior="Forever" Duration="0:0:10">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="DataContext.Synchronizer" Duration="0:0:0.6">
<DiscreteDoubleKeyFrame Value="1" KeyTime="0:0:0.0"/>
<DiscreteDoubleKeyFrame Value="0" KeyTime="0:0:0.6"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Window.Triggers>
Question N: 1 In yes / no answer, is there is any work around for this exception?
Question N: 2 Is there a better solution?
Problem N: 2
The application has several styles, mainly Dark.Xaml and Light.Xaml, as we already saw in the first issue, animation is used to indicate to the user that a specific page needs some attention. in dark mode we are going to flash the icon with a red color, and in light mode we are going to flash with a blue color, so let me focus on this part of the code:
<ColorAnimationUsingKeyFrames Duration="0:0:0.6" Storyboard.TargetProperty="(Label.Foreground).(SolidColorBrush.Color)">
<LinearColorKeyFrame Value="#8B0000" KeyTime="0:0:0.2"/>
<LinearColorKeyFrame Value="#272725" KeyTime="0:0:0.3"/>
<LinearColorKeyFrame Value="#8B0000" KeyTime="0:0:0.4"/>
<LinearColorKeyFrame Value="#272725" KeyTime="0:0:0.6"/>
</ColorAnimationUsingKeyFrames>
In general, I change the theme of the app using this C # code:
Resources.MergedDictionaries.Clear();
Resources.MergedDictionaries.Add(Global.Themes[i]);
It works fine with elements that have a DynamicResource binding, but for StaticResource No !!
Question: How can I change the app theme for this StoryBoard ControlTemplate, especially when there is no chance to use the Binding or the Dynamic Resource.
<ControlTemplate x:Key="Menu.Button" TargetType="Button">
<Grid>
<Label Content="{TemplateBinding Content}">
<Label.Style>
<Style TargetType="Label">
<Setter Property="Width" Value="35"/>
<Setter Property="FontSize" Value="11"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}, Path=Tag, Converter={StaticResource Check}, ConverterParameter=1|1}" Value="True"/>
<Condition Binding="{Binding Synchronizer}" Value="1"/>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.EnterActions>
<BeginStoryboard Name="Storyboard">
<Storyboard>
<ColorAnimationUsingKeyFrames Duration="0:0:0.6" Storyboard.TargetProperty="(Label.Foreground).(SolidColorBrush.Color)">
<LinearColorKeyFrame Value="#8B0000" KeyTime="0:0:0.2"/>
<LinearColorKeyFrame Value="#272725" KeyTime="0:0:0.3"/>
<LinearColorKeyFrame Value="#8B0000" KeyTime="0:0:0.4"/>
<LinearColorKeyFrame Value="#272725" KeyTime="0:0:0.6"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</MultiDataTrigger.EnterActions>
<MultiDataTrigger.ExitActions>
<RemoveStoryboard BeginStoryboardName="Storyboard"/>
</MultiDataTrigger.ExitActions>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
<Label>
<Label.Style>
<Style TargetType="Label">
<Setter Property="Width" Value="2"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}, Path=Tag, Converter={StaticResource Check}, ConverterParameter=0|0}" Value="True"/>
</MultiDataTrigger.Conditions>
<Setter Property="Visibility" Value="Collapsed"></Setter>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
</Grid>
</ControlTemplate>
<StackPanel Name="Menu" DockPanel.Dock="Left" Width="35" Orientation="Vertical" VerticalAlignment="Bottom">
<Button Template="{StaticResource Menu.Button}"/>
<Button Template="{StaticResource Menu.Button}"/>
<Button Template="{StaticResource Menu.Button}"/>
<Button Template="{StaticResource Menu.Button}"/>
<Button Template="{StaticResource Menu.Button}"/>
<Button Template="{StaticResource Menu.Button}"/>
<Button Template="{StaticResource Menu.Button}"/>
<Button Template="{StaticResource Menu.Button}"/>
<Button Template="{StaticResource Menu.Button}"/>
<Button Template="{StaticResource Menu.Button}"/>
<Button Template="{StaticResource Menu.Button}"/>
<Button Template="{StaticResource Menu.Button}"/>
<Button Template="{StaticResource Menu.Button}"/>
<Button Template="{StaticResource Menu.Button}"/>
</StackPanel>
You cannot get around the problems you're facing using XAML alone. This is because Storyboards in XAML are frozen and you cannot alter them in any way.
The way I handle this is that I move any animations that need dynamic capabilities such as databinding or theme switching into code and I make them available as XAML/attached behaviors.

Storyboard.TargetProperty path contains nonanimatable property 'Text

Edit:
I'am trying to change Text of TextBox with event trigger, But I am getting a run time error like below.
System.InvalidOperationException: ''(0)' Storyboard.TargetProperty path contains nonanimatable property 'Text'.'
How to change Text with event trigger in WPF
<Style x:Key="mystyle"
TargetType="{x:Type TextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<StackPanel>
<ScrollViewer x:Name="PART_ContentHost"
Focusable="false"
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto" />
<ToggleButton HorizontalAlignment="Right"
VerticalAlignment="Top"
Content="search"
Name="searchButton">
<ToggleButton.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<StringAnimationUsingKeyFrames Storyboard.Target="{Binding RelativeSource={RelativeSource AncestorType=TextBox,AncestorLevel=1}}"
Storyboard.TargetProperty="(TextBox.Text)">
<DiscreteStringKeyFrame KeyTime="00:00:00"
Value="texttwo" />
</StringAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ToggleButton.Triggers>
</ToggleButton>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Edit: since you have totally rewritten the original question, my original answer does not make sense anymore, so I will rewrite it as well.
The problem is that in the EventTrigger you can only use a StoryBoard, and you cannot set the Text property of the TextBox from it. Therefore I think even if it can be achieved purely from WPF with a Template, the solution would be so complicated and ugly that it does not worth it, so I would suggest to create a user control.
If we make a step backward, what is your goal with this customized TextBox?
Edit2:
Finally I could do it with a custom animation class, but I still think that implementing this functionality with a user control is the good solution.
This is the custom animation class (for sake of simplicity I have put it in "local" namespace):
public class TextBoxStringAnimation : StringAnimationBase {
public static readonly DependencyProperty TextBoxToChangeProperty = DependencyProperty.Register(nameof(TextBoxToChange), typeof(TextBox), typeof(TextBoxStringAnimation));
public TextBox TextBoxToChange {
get => (TextBox)this.GetValue(TextBoxToChangeProperty);
set => this.SetValue(TextBoxToChangeProperty, value);
}
public static readonly DependencyProperty NewTextProperty = DependencyProperty.Register(nameof(NewText), typeof(string), typeof(TextBoxStringAnimation));
public string NewText {
get => (string)this.GetValue(NewTextProperty);
set => this.SetValue(NewTextProperty, value);
}
protected override Freezable CreateInstanceCore() => new TextBoxStringAnimation();
protected override string GetCurrentValueCore(string defaultOriginValue, string defaultDestinationValue, AnimationClock animationClock) {
TextBoxToChange.Text = NewText;
return defaultDestinationValue;
}
protected override bool FreezeCore(bool isChecking) {
return true;
}
}
This inherits from StringAnimationBase, and you can set the TextBox and the NewText values directly. I have implemented both as dependency properties, so you can bind them.
When getting the current value (GetCurrentValueCore) it simply sets the Text property of the target TextBox. I had to override FreezeCore, because by default it has returned false, and that causes an InvelidOperationException when the animation is triggered.
So this is an animation that does not animate at all. :) I consider this an ugly solution, but without using a user control I could not come up with a better solution.
Below is the XAML markup. You must set the TargetProperty of the animation, although at the end it is not used - that is why I have specified Tag. If you use the Tag property of the textbox, check if the animation resets it or not.
<Style x:Key="mystyle" TargetType="{x:Type TextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<StackPanel>
<ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" />
<ToggleButton HorizontalAlignment="Right" VerticalAlignment="Top" Content="search" Name="searchButton">
<ToggleButton.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<local:TextBoxStringAnimation TextBoxToChange="{Binding RelativeSource={RelativeSource AncestorType=TextBox,AncestorLevel=1}}"
NewText="texttwo" Storyboard.TargetProperty="(TextBox.Tag)"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ToggleButton.Triggers>
</ToggleButton>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Create A Custom Event That Can Be Triggered From Code Behind

I'm breaking my pick on something I would have thought to be pretty simple. We have an application which uses some advanced color animations on a panel or a border control to attract the users attention when specific conditions occur. Usually those conditions are identified by communicating with an external device and could occur at any time. So I want to be able to define a trigger for a border or stackpanel like I might for it's standard IsEnabled or IsFocused properties but one that I can trigger arbitrarily form the Main Window's code-behind (IsMyArbitraryCondition). I imagine it would look like this:
<Border x:Name="Fancy_Border">
<Border.Style>
<Style TargetType="Border">
<Setter Property="CornerRadius" Value="5"/>
<Setter Property="BorderThickness" Value="5"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Style.Triggers>
<Trigger Property="IsMyArbitraryCondition" Value="true">
<Trigger.EnterActions>
<BeginStoryboard x:Name="Board" Storyboard="{StaticResource ComplicatedAnimation}"/>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>
Then in the code-behind for the main window:
Fancy_Border.IsMyArbitraryCondition = true;
// ComplicatedAnimation occurs
I've seen attached properties, dependency properties, etc suggested but my level of knowledge about how to us WPF has been insufficient so far to use those examples successfully. It seems like there must be a relatively simple way that I can still define my complex trigger behavior with the convenience of an XAML style but have that style trigger fired by something (anything!) other than the built in properties (IsMouseOver, IsPressed, IsVisible, etc etc).
EDIT (Using UserControl And DataTrigger)
I have a complete and working example provided below. The only remaining issue is that I can't put named components inside the content of my extended border control. The compiler returns:
Cannot set Name attribute value 'Example' on element 'TextBlock'. 'TextBlock' is under the scope of element 'HighlightBorder', which already had a name registered when it was defined in another scope.
This is an issue as I'm not developing using MVVM and seek to directly manipulated some individual controls that are within the HighlightBorder. Any workarounds you know of for that would be very helpful!
HighlightBorder.cs
using System;
using System.Windows;
using System.Windows.Controls;
namespace App
{
public partial class HighlightBorder : Border
{
public HighlightBorder()
{
InitializeComponent();
}
public bool IsActiveHighlight
{
get { return (bool) GetValue(ActiveHighlightProperty); }
set { SetValue(ActiveHighlightProperty, value); }
}
public static readonly DependencyProperty ActiveHighlightProperty =
DependencyProperty.Register("IsActiveHighlight", typeof(bool), typeof(HighlightBorder), new UIPropertyMetadata(null));
}
}
HighlightBorder.xaml
<Border x:Class="App.HighlightBorder"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Border.Style>
<Style TargetType="Border">
<Setter Property="CornerRadius" Value="5"/>
<Setter Property="BorderThickness" Value="5"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsActiveHighlight, RelativeSource={RelativeSource Mode=Self}}" Value="true">
<DataTrigger.EnterActions>
<BeginStoryboard x:Name="EnabledPulse" Storyboard="{DynamicResource PulseAccent}"/>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="EnabledPulse"/>
<BeginStoryboard x:Name="EnabledClear" Storyboard="{DynamicResource ClearAccent}"/>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>
MainWindow.xaml
<local:HighlightBorder x:Name="Grouped_Controls">
<TextBlock> Example Content </TextBlock>
</local:HighlightBorder>
MainWindow.cs
Grouped_Controls.IsActiveHighlight = false; // Or true

WPF - System.InvalidOperationException on ContextMenu.IsOpen

I was given the following exception:
An unhandled exception of type 'System.InvalidOperationException' occurred in PresentationFramework.dll
Additional information: Cannot resolve all property references in the property path 'ContextMenu.IsOpen'. Verify that applicable objects support the properties.
I guess the exception is quite self-explanatory, however I have no idea on how to fix it.
Here is my code:
XAML
<Button
x:Name="btnNotifications"
Height="50px"
Width="auto"
Padding="15 0"
Click="btnNotifications_Click"
ToolTip="Notifications & Agenda"
HorizontalAlignment="Right"
DockPanel.Dock="Right"
BorderThickness="0">
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{DynamicResource AccentColorBrush}"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="False">
<Setter Property="Background" Value="Transparent"/>
</Trigger>
<EventTrigger RoutedEvent="Click">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="ContextMenu.IsOpen">
<DiscreteBooleanKeyFrame KeyTime="0:0:0" Value="True"/>
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
</Button.Style>
<Button.Content>
<StackPanel
Orientation="Horizontal">
<Image
Source="/Resources/Icons/Notifications.ico"
Width="25px"
Height="25px"/>
<Label
x:Name="lblNotifications"
FontFamily="Century Gothic"
FontSize="25px"
Foreground="Maroon"
Visibility="Collapsed"/>
</StackPanel>
</Button.Content>
<Button.ContextMenu>
<ContextMenu
x:Name="btnNotificationsMenu">
<MenuItem
x:Name="btnNotificationsNoNew"
Header="No New Notifications."/>
<MenuItem
x:Name="btnNotificationsSeperator"
Background="{DynamicResource AccentColorBrush}"
Height="2px"
Focusable="False"
IsHitTestVisible="False"/>
<MenuItem
x:Name="btnNotificationsNoAgenda"
Header="Your Agenda is Empty."/>
</ContextMenu>
</Button.ContextMenu>
</Button>
Code Behind
public static void NewAppointmentForm()
{
MainWindow appointment = new MainWindow(new AppointmentForm(true));
appointment.btnNotificationsMenu.IsOpen = false;
appointment.ShowDialog();
}
Obviously wrapping the above code in a try catch and calling Close() on appointment fixes the issue. However, it is more of a workaround than a clean solution.
This issue occurs whenever I try to close the window through another Button. I tried closing the window using Close() method within an EventHandler and also as a command through XAML - Command="{Binding CloseCommand}".
I would be really grateful if someone could shed some light upon this issue.
May I point out that the Button containing the ContextMenu is wrapped inside a Border which is placed directly in the MainWindow.
If more detail is needed, please do ask. Thanks :)
Try surrounding the property with parenthesis:
Storyboard.TargetProperty="(ContextMenu.IsOpen)"
See PropertyPath XAML Syntax. The XAML parser doesn't know how to resolve the property because it can be attached to any DependencyObject.
This was a typical Isaac silly mistake.
Basically, I copied the Button which had the ContextMenu and pasted the code to create two ContextMenu-less buttons. Having the following applied to the ContextMenu-less buttons caused the program to crash:
<EventTrigger RoutedEvent="Click">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="ContextMenu.IsOpen">
<DiscreteBooleanKeyFrame KeyTime="0:0:0" Value="True"/>
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>

Background property does not point to a dependencyobject in path '(0).(1)'

I wrote this code and got an exception:
Background property does not point to a dependencyobject in path '(0).(1)'
I saw this problem in other posts in the forum but didn't founded a solution.
<WrapPanel.Style>
<Style>
<Style.Triggers>
<Trigger Property "WrapPanel.Visibility" Value="Visible">
<Trigger.EnterActions>
<BeginStoryboard HandoffBehavior="Compose">
<Storyboard RepeatBehavior="Forever" AutoReverse="True">
<ColorAnimation
Storyboard.TargetProperty="(WrapPanel.Background).(SolidColorBrush.Color)"
Duration="00:00:01" To="Red"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>
</WrapPanel.Style>
Any help with this?
You most likely failed to set a value for the initial background brush. You can either do so with a style setter, or else just set a value on the panel directly. The style setter is probably better:
<Setter Property="Background">
<Setter.Value>
<SolidColorBrush Color="Blue"/>
</Setter.Value>
</Setter>
Note that you can also specify the TargetType property on your style, so that you don't have to prefix all property reference with WrapPanel:
<Style TargetType="WrapPanel">
You must set the Background property of the WrapPanel! Otherwise the WPF subsystem doesn't recognize it as a SolidColorBrush (could be another brush as well).
<WrapPanel Background="White">
...
</WrapPanel>
is sufficient.

Categories

Resources