Trigger storyboard on Button click? - xaml

When I try to start my app with this code it throws an exception saying error text cannot be found.
<Button>
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:05"
To="1" From="0"
Storyboard.TargetName="ContentGrid"
Storyboard.TargetProperty="Opacity" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
Seems like something wrong with the routed event property. What will fix this exception.

I think the best way is to use a Behavior. It's their purpose to extend the functions of basic controls combined with reusability. You can see a snippet right over here on Windows blog (and as I see, it's a part of the framework in Namespace: Microsoft.Xaml.Interactions.Core Assembly: Microsoft.Xaml.Interactions in Microsoft.Xaml.Interactions.dll).
<Button x:Name="button">
<Interactivity:Interaction.Behaviors>
<Core:EventTriggerBehavior EventName="Click">
<Media:ControlStoryboardAction Storyboard="storyboard1"/>
</Core:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
</Button>

Related

UWP - FadeIn effect on background image

I need a fade in effect on my background image. During the runtime the imagesource can be changed, which works with the setted binding as expected. Anyway the correspondending animation doesn't take any visual effects. At the moment my xaml looks like the following:
xmlns:Interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:Core="using:Microsoft.Xaml.Interactions.Core"
xmlns:Media="using:Microsoft.Xaml.Interactions.Media"
<Page.Content>
<Grid>
<Grid.Background>
<ImageBrush x:Name="image" ImageSource="{Binding Path=ImageSource,UpdateSourceTrigger=PropertyChanged}" Stretch="UniformToFill" >
<Interactivity:Interaction.Behaviors>
<Core:EventTriggerBehavior EventName="ImageOpened" >
<Media:ControlStoryboardAction ControlStoryboardOption="Play">
<Media:ControlStoryboardAction.Storyboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:1" Storyboard.TargetName="image"/>
</Storyboard>
</Media:ControlStoryboardAction.Storyboard>
</Media:ControlStoryboardAction>
</Core:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
</ImageBrush>
</Grid.Background>
When I use instead:
[...]
<Media:ControlStoryboardAction.Storyboard>
<Storyboard>
<FadeInThemeAnimation Storyboard.TargetName="Image" />
</Storyboard>
</Media:ControlStoryboardAction.Storyboard>
I get
System.Runtime.InteropServices.COMException: No installed components were detected.
Cannot resolve TargetName Image.
at Windows.UI.Xaml.Media.Animation.Storyboard.Begin()
at Microsoft.Xaml.Interactions.Media.ControlStoryboardAction.Execute(Object sender, Object parameter)
at Microsoft.Xaml.Interactivity.Interaction.ExecuteActions(Object sender, ActionCollection actions, Object parameter)
at Microsoft.Xaml.Interactions.Core.EventTriggerBehavior.OnEvent(Object sender, Object eventArgs)
Any ideas?
[Edit]
Thanks to the answer of #SWilko, I determine that the Animation only works on a Image. My code above works if I change the ImageBrush to a Image and I place it into the grid (not Grid.Background).
Wouldn't it be easier to use an Image control and add further controls on top as needed eg
<Grid x:Name="LayoutGrid">
<Image x:Name="image" Stretch="UniformToFill"
Source="{Binding Path=ImageSource,UpdateSourceTrigger=PropertyChanged}"
Opacity="0" Visibility="Collapsed">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="ImageOpened">
<media:ControlStoryboardAction x:Name="sbAction" ControlStoryboardOption="Play">
<media:ControlStoryboardAction.Storyboard>
<Storyboard x:Name="sb">
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="image">
<DiscreteObjectKeyFrame KeyTime="00:00:00">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)"
Storyboard.TargetName="image">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:3" Value="0.5"/>
<EasingDoubleKeyFrame KeyTime="0:0:5" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</media:ControlStoryboardAction.Storyboard>
</media:ControlStoryboardAction>
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</Image>
</Grid>
EDIT
To update the image and start the animation from scratch.
I've added Visibility toggle animation to the Storyboard and named the Storyboard sb
Now in code behind I've used the Storyboard Completed event to change the image and restart the animation. You could do this where appropriate for your app this is just to show an example.
eg
sb.Completed += (sender, e) =>
{
//this is a local image for me you would probably update your ImageSource property here
var newimg = new BitmapImage(new Uri("ms-appx:///Assets/rock.jpg"));
image.Source = newimg;
image.Opacity = 0;
image.Visibility = Visibility.Collpased;
sb.Begin();
};

UWP ListviewItem Customize Pointer Events preserving Drag & Drop functionality

Following this question, I'm with the same and other doubts.
Like the user #fipcurren88 I were using Buttons inside ListView ItemTemplate to customize the behavior of pointer events (Pointer Over and Pressed). This is the way I usually do it until I found Drag and Drop didn't work and using a Button inside a ItemTemplate is the wrong approach (like #Filip Skakun mentioned in the same question).
Removing the custom Button and using Itemtemplate directly with the content I want (an Image for example - the custom Button content) I didn't knew how to set the background colors for other states (pointer over and pressed for example). I found out the solution using ListViewItemPresenter in the ItemContainerStyle were I can set different backgrounds to each Pointer Event.
But, I lost the PointerDownThemeAnimation on the Item and I don't know how to get it back. Using a Button is easy, but it affects the Drag and Drop functionality.
This is the Problem Number 1.
This works with simple Items (a single Image), but imagine I have a more complex Item (a Image, a Grid and a TextBlock inside the Grid). I want to change the Grid Background (or the Textblock Foreground) while Pointer is over and/or while the pressed event.
In this case I know the ListViewItemPresenter solution will not work. I need a more specific way to define the different states (VisualStateManager, Common States). Using a custom Button will affect the Drag and Drop functionality (the starting point of the other thread).
What can I do?!
Let's call this Problem Number 2.
Any UWP/XAML Expert that can clear me mind? Thank you.
These requests can all be done in the xaml code by modifying the ListViewItem styles and templates, and doing this will not affect the Drag and Drop function of ListView.
For your both questions, you can copy the style of x:Key="ListViewItemExpanded" into your Page.Resource and remove the x:Key="ListViewItemExpanded", so will this style be applied to all the ListViewItems in your page.
If you have Grid, Image, and TextBlock together in an item, you can set ListView like this:
<ListView x:Name="listView">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Height="100" Width="100" Grid.Column="0"
Source="{Binding image}" />
<TextBlock Grid.Column="1" FontSize="20" Text="{Binding txt}" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Then if you want to change the background of the item and the the foreground of your text when your item is in PointerOver or Pressed state, you just need to find this two VisualStates in the style and for example modify them like this:
<VisualState x:Name="PointerOver">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="BorderBackground" Storyboard.TargetProperty="Opacity" Duration="0" To="1" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderBackground" Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0" Value="Blue" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="Red" />
</ObjectAnimationUsingKeyFrames>
<PointerUpThemeAnimation Storyboard.TargetName="ContentPresenter" />
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="BorderBackground" Storyboard.TargetProperty="Opacity" Duration="0" To="1" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderBackground" Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0" Value="Red" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="Blue" />
</ObjectAnimationUsingKeyFrames>
<PointerDownThemeAnimation TargetName="ContentPresenter" />
</Storyboard>
</VisualState>
By doing this, the Background targets the background of the whole item, not just the Grid. The Grid will adapt to the controls inside it even you set HorizontalAlignment="Stretch" to the Grid by default, this is because by default it uses ContentPresent like this:
<ContentPresenter x:Name="ContentPresenter"
ContentTransitions="{TemplateBinding ContentTransitions}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Margin="{TemplateBinding Padding}" />
If you change the HorizontalAlignment and VerticalAlignment properties in the style to Stretch, your Grid in the DateTemplate will fill the whole item. In this scenario, changing the Background of BorderBackground and the Foreground of ContentPresenter in the visual state can still work.

Eventrigger routed event for AppBarButton?

How would I make this storyboard go off on a click in the windows 10 uwp? My app just crashes on initialize component.
<AppBarButton x:Name="nextButton" Label="next" Icon="Forward" Click="nextButton_Click">
<AppBarButton.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="messageTextBlock"
Storyboard.TargetProperty="(TextBlock.Opacity)"
To="0.0" From="1.0" Duration="0:0:01" />
</Storyboard>
</EventTrigger>
</AppBarButton.Triggers>
</AppBarButton>

How to combine Storyboards in XAML?

I'm looking for some way to combine storyboards into other storyboards in XAML.
In the following example, Thing1 and Thing2 are two TextBlocks that slide onto a Canvas from the top and bottom, respectively. I intend that only one, the other, or neither is visible at any time, so I set up three states in the VisualStateManager, inside a single VisualStateGroup, with Transitions among the various states.
I'd like to be able to write the Storyboards for Thing1ToThing2 and Thing2ToThing1 in the context of the other, simpler Storyboards. For instance, is there any way to have the storyboard Thing1ToThing2 call/invoke/reference/be composed of Thing1Out and Thing2In? The code can be duplicated, of course, but can we do any better than that? Or, is there a way to have the VisualTransitions do more?
I'd prefer to keep this in XAML, if possible, and in a way that scales for larger numbers of things.
Thanks!
-David
<UserControl x:Class="WpfApplication1.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="500" Height="500" Background="PaleTurquoise" >
<UserControl.Resources>
<Storyboard x:Key="Thing1In">
<DoubleAnimation Storyboard.TargetName="Thing1" Storyboard.TargetProperty="(Canvas.Top)" Duration="0:0:2" To="100" />
</Storyboard>
<Storyboard x:Key="Thing1Out">
<DoubleAnimation Storyboard.TargetName="Thing1" Storyboard.TargetProperty="(Canvas.Top)" Duration="0:0:2" To="-100" />
</Storyboard>
<Storyboard x:Key="Thing2In">
<DoubleAnimation Storyboard.TargetName="Thing2" Storyboard.TargetProperty="(Canvas.Bottom)" Duration="0:0:2" To="100" />
</Storyboard>
<Storyboard x:Key="Thing2Out">
<DoubleAnimation Storyboard.TargetName="Thing2" Storyboard.TargetProperty="(Canvas.Bottom)" Duration="0:0:2" To="-100" />
</Storyboard>
<Storyboard x:Key="Thing1ToThing2">
<!--do Thing1Out then (or at the same time as) Thing2In-->
</Storyboard>
<Storyboard x:Key="Thing2ToThing1">
<!--do Thing2Out then (or at the same time as) Thing1In-->
</Storyboard>
</UserControl.Resources>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ThingStates">
<VisualState x:Name="NothingInState" />
<VisualState x:Name="Thing1InState" Storyboard="{StaticResource Thing1In}" />
<VisualState x:Name="Thing2InState" Storyboard="{StaticResource Thing2In}" />
<VisualStateGroup.Transitions>
<VisualTransition From="Thing1InState" To="Thing2InState" Storyboard="{StaticResource Thing1ToThing2}" />
<VisualTransition From="Thing2InState" To="Thing1InState" Storyboard="{StaticResource Thing2ToThing1}" />
<VisualTransition From="Thing1InState" To="NothingInState" Storyboard="{StaticResource Thing1Out}" />
<VisualTransition From="Thing2InState" To="NothingInState" Storyboard="{StaticResource Thing2Out}" />
</VisualStateGroup.Transitions>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Canvas ClipToBounds="True">
<TextBlock x:Name="Thing1" Text="Thing1" FontSize="60" Canvas.Top="-100" Canvas.Left="100" />
<TextBlock x:Name="Thing2" Text="Thing2" FontSize="60" Canvas.Bottom="-100" Canvas.Left="100" />
</Canvas>
</UserControl>

XAML property to start a storyboard animation on load

Well, as the title suggests:
I have a storyboard and I want it's animation to start without the intervention of code.
The reason for this requirement is that I am targeting Silverlight Embedded and I am too lazy right now to recompile my application as well. And, coming to think of it, it will be easier to change the animation only in the future.
Does XAML have a property to make the storyboard run as soon as the xaml loads?
You can use the Loaded event to start your storyboard
See MSDN for an example:
Storyboard (Silverlight)
Picked the example from MSDN:
<Canvas
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Rectangle
x:Name="MyAnimatedRectangle"
Width="100"
Height="100"
Fill="Blue">
<Rectangle.Triggers>
<!-- Animates the rectangle's opacity.
This is the important part, the EventTrigger which will start our animation -->
<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="MyAnimatedRectangle"
Storyboard.TargetProperty="Opacity"
From="1.0" To="0.0" Duration="0:0:5" AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
</Canvas>
The object Rectangle has properties. In the Triggers property we defined an EventTrigger which will fire when this event will occur. We choose the Rectangle.Loaded event, which means it will fire when loaded ;).
We add a BeginStoryboard property to begin our storyboard, and add a Storyboard. This animation will use a DoubleAnimation on the Opacity property, which means that in a duration of 5 seconds, the opacity will gradually fade to zero, and back (AutoReverse property) and it will do this Forever (the RepeatBehaviour property).
<UserControl x:Class="SOSMVVM.AniM11"
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:DesignWidth='640'
d:DesignHeight='480'>
<StackPanel Margin="5">
<Rectangle Name="rect3" Fill="Blue" Margin="2" Width="20"
Height="20" HorizontalAlignment="Left" />
<Button Margin="2,20,0,0" HorizontalAlignment="Left"
Content="Start Animations" Width="100">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="rect3" Storyboard.TargetProperty="Width"
From="20" To="400" Duration="0:0:10" SpeedRatio="0.5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Button.Triggers>
</Button>
</StackPanel>
</UserControl>