Silverlight Storyboard of DataTemplate - c#

I'm working on Horizontal List, where each item gets expanded as you hover the mouse over it.
I have read few tutorials and I'm able to create simple animation with MouseEnter and MouseLeave events however, it doesnt work in my datatemplate.
ATTEMPT 1
<DataTemplate x:Key="StepBreadcrumbItem">
<Border BorderBrush="Gray" HorizontalAlignment="Stretch" Width="60">
<Border.Triggers>
<EventTrigger RoutedEvent="Border.MouseEnter">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:0.5" To="100" Storyboard.TargetProperty="(FrameworkElement.Width)" d:IsOptimized="True"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Border.MouseLeave">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation BeginTime="0:0:1" Duration="0:0:0.5" To="60" Storyboard.TargetProperty="(FrameworkElement.Width)" d:IsOptimized="True"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Border.Triggers>
<StackPanel Orientation="Horizontal">
<TextBlock Text=" > " />
<TextBlock Text="{Binding Order, Mode=OneWay, StringFormat='{}. '}"/>
<TextBlock Text="{Binding Name, Mode=OneWay}"/>
</StackPanel>
</Border>
</DataTemplate>
What am I missing? It works fine for a single element. I get runtime error Error: Unhandled Error in Silverlight Application
Code: 2531
Category: ParserError
Message: Failed to assign to property 'System.Windows.EventTrigger.RoutedEvent'.
ATTEMPT 2
I have now implemented it differently using MouseEnter event. Since attempt 1 failed.
<DataTemplate x:Key="StepBreadcrumbItem">
<Border BorderBrush="Gray" HorizontalAlignment="Stretch" Width="60" MouseLeave="CollapseBreadcrumb" MouseEnter="ExpandBreadcrumb">
<StackPanel Orientation="Horizontal">
<TextBlock Text=" > " />
<TextBlock Text="{Binding Order, Mode=OneWay, StringFormat='{}. '}"/>
<TextBlock Text="{Binding Name, Mode=OneWay}"/>
</StackPanel>
</Border>
</DataTemplate>
private void CollapseBreadcrumb(object sender, System.Windows.Input.MouseEventArgs e)
{
var border = sender as Border;
var duration = TimeSpan.FromMilliseconds(1000);
var sb = new Storyboard { Duration = duration };
var doubleAnimation = new DoubleAnimation
{
BeginTime = TimeSpan.FromSeconds(1),
Duration = duration,
To = 50
};
sb.Children.Add(doubleAnimation);
Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath("(FrameworkElement.Width)"));
Storyboard.SetTarget(doubleAnimation, border);
sb.Begin();
}
private void ExpandBreadcrumb(object sender, System.Windows.Input.MouseEventArgs e)
{
var border = sender as Border;
var duration = TimeSpan.FromMilliseconds(1000);
var sb = new Storyboard {Duration = duration};
var doubleAnimation = new DoubleAnimation
{
BeginTime = TimeSpan.FromSeconds(0),
Duration = duration,
To = 100
};
sb.Children.Add(doubleAnimation);
Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath("(FrameworkElement.Width)"));
Storyboard.SetTarget(doubleAnimation, border);
sb.Begin();
}
However, now it only expands when I have mouse over it, it stops when I do mouse leave and it doesn't run collapse. Also the reason why I set-up storyboard pro grammatically is because when I defined two storyboards and was just reassigning and running it to different item it looked very bad when I was moving my mouse across all list items.

Unfortunately Silverlight only supports Loaded EventTrigger.
The workaround is pretty easy, use Behaviors. You just need to either use ControlStoryboardAction or GoToStateAction to trigger the animation.
Something like this,
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter">
<ei:ControlStoryboardAction Storyboard="{StaticResource Storyboard1}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
This and this could be a good start. :)
Update
You better do this kind of animation in your xaml. Basically you need to create a visual state group that has two states, Normal and MouseOver. And then trigger them using GoToStateAction.
You would have something like this,
<Border x:Name="border" Width="60" Background="Gray">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="VisualStateGroup">
<VisualStateGroup.Transitions>
<VisualTransition/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<!-- your storyboard here -->
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeave">
<ei:GoToStateAction StateName="Normal"/>
</i:EventTrigger>
<i:EventTrigger EventName="MouseEnter">
<ei:GoToStateAction StateName="MouseOver"/>
</i:EventTrigger>
</i:Interaction.Triggers>
Update 2
Actually you don't even need to create visual state group... Just use ControlStoryboardAction like this.
<DataTemplate x:Key="ItemTemplate">
<Border x:Name="border" Width="60" Background="Gray" RenderTransformOrigin="0.5,0.5">
<Border.Resources>
<Storyboard x:Name="expand">
<DoubleAnimation Duration="0:0:0.4" To="100" Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="border" d:IsOptimized="True"/>
</Storyboard>
<Storyboard x:Name="collapse">
<DoubleAnimation Duration="0:0:0.4" To="60" Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="border" d:IsOptimized="True"/>
</Storyboard>
</Border.Resources>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeave">
<ei:ControlStoryboardAction Storyboard="{StaticResource collapse}"/>
</i:EventTrigger>
<i:EventTrigger EventName="MouseEnter">
<ei:ControlStoryboardAction Storyboard="{StaticResource expand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<StackPanel Height="32" Width="26">
<TextBlock Text="{Binding Name}"/>
<TextBlock Text="{Binding Order}"/>
</StackPanel>
</Border>
</DataTemplate>

Related

Rotate image inside a button UWP

I'm trying to rotate a font icon inside a button 90° in the first click and back to 0° on the second click.
Currently I have:
<Page.Resources>
<Storyboard x:Name="RotateButton90Degrees">
<DoubleAnimation
EnableDependentAnimation="True"
Storyboard.TargetName="ShowSubTasks_ButtonRotateTransform"
Storyboard.TargetProperty="Angle"
From="0"
To="90"
Duration="350" />
</Storyboard>
</Page.Resources>
<Button
x:Name="ShowSubTasks_Button"
Background="Transparent">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Click">
<media:ControlStoryboardAction Storyboard="{StaticResource RotateButton90Degrees}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
<FontIcon
FontFamily="Segoe MDL2 Assets"
Glyph=""
RenderTransformOrigin="0.5, 0.5">
<FontIcon.RenderTransform>
<RotateTransform x:Name="ShowSubTasks_ButtonRotateTransform" />
</FontIcon.RenderTransform>
</FontIcon>
</Button>
The problem is that the app crashes when I click the button (it's not finding the ShowSubTasks_ButtonRotateTransform). The second is that I don't know how to revert the rotation effect after the first click (first click -> 90°, second click -> 0°, third click -> 90° and so on).
Any help would be appreciated.
Ok i got the problem, the thing is that im running all that code inside a DataTemplate ... So that explains why its crashing. For the fix i used what #Dishant suggested, created two storyboards and with a DataTriggerBehavior i change the angle of the rotate transform
<StackPanel.Resources>
<Storyboard x:Name="RotateButtonTo90Degrees">
<DoubleAnimation
EnableDependentAnimation="True"
Storyboard.TargetName="ShowSubTasks_ButtonRotateTransform"
Storyboard.TargetProperty="Angle"
From="0"
To="90"
Duration="0:0:0.1" />
</Storyboard>
<Storyboard x:Name="RotateButtonTo0Degrees">
<DoubleAnimation
EnableDependentAnimation="True"
Storyboard.TargetName="ShowSubTasks_ButtonRotateTransform"
Storyboard.TargetProperty="Angle"
From="90"
To="0"
Duration="0:0:0.1" />
</Storyboard>
</StackPanel.Resources>
<Button
Background="Transparent"
Visibility="{Binding HasSubTasks, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}">
<interactivity:Interaction.Behaviors>
<core:DataTriggerBehavior Binding="{Binding ShowSubTasks, Mode=OneWay}" Value="True">
<media:ControlStoryboardAction Storyboard="{StaticResource RotateButtonTo90Degrees}" />
</core:DataTriggerBehavior>
<core:DataTriggerBehavior Binding="{Binding ShowSubTasks, Mode=OneWay}" Value="False">
<media:ControlStoryboardAction Storyboard="{StaticResource RotateButtonTo0Degrees}" />
</core:DataTriggerBehavior>
</interactivity:Interaction.Behaviors>
<FontIcon
FontFamily="Segoe MDL2 Assets"
Glyph=""
RenderTransformOrigin="0.5, 0.5">
<FontIcon.RenderTransform>
<RotateTransform x:Name="ShowSubTasks_ButtonRotateTransform" />
</FontIcon.RenderTransform>
</FontIcon>
</Button>
Also as #MartinZikmund suggested, i needed to change the duration from 350 to something like 0:0:0.5
In my case the app does not crash, but the icon does not rotate, because the duration is set to 350, which basically means 350 hours. If you change this value to something like 0:0:0.5, it should rotate in 0.5 seconds. To do the reverse animation, you would probably need to set the animation target programatically, but in such case you could just run the storyboard itself in the Click event handler.
If you are targeting Windows 10 15063 or higher, you can use Implicit Animations in XAML. In that case you could set up an implicit animation on the rotation of the icon and then just set the rotation property in the code-behind accordingly and implicit animation would take care of the animation itself.

WPF: add blur effect on button when mouse is on that button-MouseEnter

I'm trying to make a simple animation - when mouse cursor is on button I want to add blur effect on that button.
So far I have this.:
<Button x:Name="button_Copy" Content="Leaderboard" HorizontalAlignment="Left" Margin="311,217,0,0" VerticalAlignment="Top" Width="139" Height="34" Background="{x:Null}" BorderBrush="{x:Null}" FontSize="22" FontWeight="Bold" Foreground="#FFE2DBDB" IsHitTestVisible="True" Click="button_Copy_Click">
<Button.Triggers>
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation From="10" To="0" Duration="0:0:0.1"
Storyboard.TargetName="blurEffect" Storyboard.TargetProperty="Radius"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
Build is succesfull, but when I take cursor over that button program immediately crashes... Any idea how to fix this?
I see you probably took your example from here.
You are missing the object BlurEffect as shown within the TextBox item as below:
<TextBlock Name="TxtSample" TextAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" Text="This is a sample and first test freetext">
<TextBlock.Effect>
<BlurEffect Radius="10" x:Name="blurEffect"/>
</TextBlock.Effect>
</TextBlock>

How can I animate a TextBlock when a SelectionChanged() event of a ListBox is called?

In the code below, I want to start the animation when there's TextChanged() event of TextBlock is called. But when I try this code, I get an error...
"Failed to assign to property 'System.Windows.EventTrigger.RoutedEvent'"
I am lost, could someone please assist me that how can I do this?
<StackPanel>
<ListBox Name"lstSample" SelectionChanged="lstSample_SelectionChanged">
<ListBox.Triggers>
<EventTrigger RoutedEvent="ListBox.SelectionChanged">
<BeginStoryboard>
<BeginStoryboard.Storyboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="txtSample" Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:1.0">
<DoubleAnimation.EasingFunction>
<PowerEase EasingMode="EaseIn" Power="8"/>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</BeginStoryboard.Storyboard>
</BeginStoryboard>
</EventTrigger>
</ListBoxTriggers>
</ListBox>
<Border Name="brdrTextSampleLanguageOne" BorderThickness="0" BorderBrush="{StaticResource PhoneAccentBrush}">
<TextBlock
Text="This is sample text."
Name="txtSample"
TextAlignment="Right"
VerticalAlignment="Center" />
</Border>
</StackPanel>
Thanks very much.
Would be really easy using code, just create a property like:
private string _textBlockText;
public string textBlockText
{
get { return _textBlockText; }
set
{
if (txtSample.Text != value)
{
if (Storyboard1.GetCurrentState() != ClockState.Active)
Storyboard1.Begin();
txtSample.Text = value;
}
}
}
Just use textBlockText property to update text in anywhere in your code and this should work like TextChanged event... Note: Storyboard1 is the animation you desire to play on TextChanged Event.
This will help you find the code below
<UserControl x:Class="WrapPanel.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit"
xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk">
<Grid x:Name="LayoutRoot"
Background="White">
<StackPanel>
<StackPanel.Resources>
<Storyboard x:Key="mystoryboard">
<DoubleAnimation Storyboard.TargetName="txtSample"
Storyboard.TargetProperty="Opacity"
From="0"
To="1"
Duration="0:0:1.0">
<DoubleAnimation.EasingFunction>
<PowerEase EasingMode="EaseIn"
Power="8" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</StackPanel.Resources>
<ListBox Name="lstSample"
SelectionChanged="lstSample_SelectionChanged">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<ei:ControlStoryboardAction ControlStoryboardOption="Play"
Storyboard="{StaticResource mystoryboard}">
</ei:ControlStoryboardAction>
</i:EventTrigger>
</i:Interaction.Triggers>
</ListBox>
<Border Name="brdrTextSampleLanguageOne"
BorderThickness="0">
<TextBlock Text="This is sample text."
Name="txtSample"
TextAlignment="Right"
VerticalAlignment="Center" />
</Border>
</StackPanel>
</Grid>
</UserControl>
Let me know if it works for you.
Cheers!
Vinod

WPF UserControl Animation wont work..?

I'm really new to WPF so if you can point me to a tutoiral as well i will be very happy :)
here is my curreny code:
<Grid Name="Grid">
<local:Card Loaded="Card_Loaded"
x:Name="MyCard">
<local:Card.Triggers>
<EventTrigger RoutedEvent="local:Card.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="MyCard"
Storyboard.TargetProperty="Opacity"
From="1.0"
To="0.0"
Duration="0:0:5"
AutoReverse="True"
RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</local:Card.Triggers>
</local:Card>
</Grid>
local:Card is a UserControl
Here is why i use x:Name="" and not Name="":
Because 'MS.Internal.Design.Metadata.ReflectionTypeNode' is implemented in the same assembly, you must set the x:Name attribute rather than the MS.Internal.Design.Metadata.ReflectionPropertyNode attribute.
And i can see the Card and everything but the Animation doesn't work =\
Here is the card XAML:
<UserControl.Resources>
<x:Array Type="{x:Type s:String}"
x:Key="src">
<s:String>Foo</s:String>
</x:Array>
<DataTemplate x:Key="frontTemplate">
<Grid Background="Transparent">
<Image Source="Images\Card.jpg" />
</Grid>
</DataTemplate>
<DataTemplate x:Key="backTemplate">
<GroupBox Header="Back"
Background="White">
<StackPanel>
<RadioButton Content="This"
IsChecked="True" />
<RadioButton Content="Is" />
<RadioButton Content="The" />
<RadioButton Content="Back" />
</StackPanel>
</GroupBox>
</DataTemplate>
</UserControl.Resources>
<ScrollViewer>
<ItemsControl Width="180"
Height="250"
ItemsSource="{StaticResource src}"
ItemTemplate="{StaticResource flipItemTemplate}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</ScrollViewer>
I copied your XAML exactly and ran it in a window. The only change I made was to replace the local:Card object with a TextBlock (since I didn't have a Card usercontrol). The animation ran perfectly.
So either your local:Card object has something strange that isn't allowing the animation to work or the Loaded="Card_Loaded" method in this line:
<local:Card Loaded="Card_Loaded" x:Name="MyCard">
is interfering with the event trigger:
<EventTrigger RoutedEvent="local:Card.Loaded">
Put the storyboard in either the EventTrigger.EnterActions or EventTrigger.Actions tags.
I recently dived in to some WPF animations....here's the link that got me started:
http://www.galasoft.ch/mydotnet/articles/article-2006102701.aspx
Solution:
<Grid Name="Grid">
<local:Card x:Name="MyCard" MouseEnter="MyCard_MouseEnter" />
</Grid>
<Window.Resources>
<Storyboard x:Key="sbdCardAnim">
<DoubleAnimation
Storyboard.TargetName="MyCard"
Storyboard.TargetProperty="Opacity"
From="1" To="0" Duration="0:0:5"
AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>
</Window.Resources>
C#:
private void MyCard_MouseEnter(object sender, MouseEventArgs e)
{
Storyboard sbdCardAnim = (Storyboard)FindResource("sbdCardAnim");
sbdCardAnim.Begin(this);
}

want a silverlight listbox with vertical marquee like effect

i want a silverlight listbox whose items are automatic scrollable (like a vertical marquee)
You might try using an ItemsControl setting the ItemsControl.ItemPanel to a StackPanel with a TranslateTransform applied on it. Then you can have a running Storyboard that adjusts the position of the Y coordinate of the Translate Transform.
EDIT: Example
<Border BorderBrush="Black" BorderThickness="2"
Height="100" Width="100"
HorizontalAlignment="Left" VerticalAlignment="Top" >
<Border.Clip>
<RectangleGeometry Rect="0,0,100,100" />
</Border.Clip>
<ItemsControl ItemsSource="{StaticResource Collection}">
<ItemsControl.RenderTransform>
<TranslateTransform x:Name="Transform" />
</ItemsControl.RenderTransform>
<i:Interaction.Triggers>
<i:EventTrigger>
<ei:ControlStoryboardAction
Storyboard="{StaticResource TransformMove}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ItemsControl>
</Border>
Then include this Storyboard in your control resources:
<Storyboard x:Key="TransformMove" Storyboard.TargetName="Transform" Storyboard.TargetProperty="Y">
<DoubleAnimation From="-100" To="100" Duration="0:0:10"
RepeatBehavior="Forever"/>
</Storyboard>

Categories