I try to display a button that shows some text. Every X seconds the button must slide to the left and reappear with a new text inside.
Due to the other object on my page I can't use a popup.
Any ideas on how to do this ?
I already try with a grid, except that I don't find how to slide it.
XAML
<Grid x:Name="PropoCloud" VerticalAlignment="Bottom">
<tut:TutorialAwareButton Name="PropoButton"
Style="{StaticResource tplButtonCloud}"
Command="{Binding CmdCreated}"
BorderThickness="0" VerticalAlignment="Bottom"
HorizontalAlignment="Left" Width="410" Height="200">
<tut:TutorialAwareButton.CommandParameter>
<cmd:NavigationCommandParameter TargetName="QuestionCreatingView"></cmd:NavigationCommandParameter>
</tut:TutorialAwareButton.CommandParameter>
</tut:TutorialAwareButton>
</Grid>
C#
private void SuggestionCycling()
{
if (PropoCloud.Visibility == Visibility.Visible)
{
PropoCloud.Visibility = Visibility.Collapsed;
}
else
{
PropoCloud.Visibility = Visibility.Visible;
}
}
Code that you have posted will only hide and show the control back again, you need to have animation to fly it out and bring it in ... have a look at this Link to understand how animation can do that...
The provided link is not for you to copy, make changes to suit your needs and understand the concept.
This is a functionnal solution :
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="FadeStates">
<VisualState x:Name="FadeOut">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="PropoCloud" Storyboard.TargetProperty="PropoCloud.Opacity" From="1" To="0" Duration="0:0:1"/>
</Storyboard>
</VisualState>
<VisualState x:Name="FadeIn">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="PropoCloud" Storyboard.TargetProperty="PropoCloud.Opacity" From="0" To="1" Duration="0:0:2"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
Just add the FadeOut.Storyboard.Begin();and FadeIn.Storyboard.Begin();In your timer cycle.
Related
I am trying to animate a button triggered by an event (not on that button) with VisualStateManager. This is my code but it doesn't work. Please help find the issue or suggest a different method to animate the button.
In the xaml file I have the following
<Grid Grid.Row="1" Grid.Column="1" DataContext="{Binding ScanningViewModel}">
<Button Height="Auto" Margin="10" x:Name="ScanButton"
HorizontalAlignment="Stretch"
Style="{DynamicResource MaterialDesignOutlinedButton}"
Command="{Binding ScanDocumentCommand}">
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon Kind="SearchAdd" Width="30" Height="30"/>
<TextBlock Margin="5,0,0,0" Text="Scanează" VerticalAlignment="Center"/>
</StackPanel>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState Name="Default">
<Storyboard/>
</VisualState>
<VisualState x:Name="MyAnimation">
<Storyboard>
<ColorAnimation
To="Pink"
Storyboard.TargetName="Stop1" Storyboard.TargetProperty="Color"
Duration="0:0:2" />
<ColorAnimation
To="Maroon"
Storyboard.TargetName="Stop2" Storyboard.TargetProperty="Color"
Duration="0:0:2" />
<ColorAnimation
To="Red"
Storyboard.TargetName="Stop1" Storyboard.TargetProperty="Color"
BeginTime="0:0:2" Duration="0:0:2" AutoReverse="True" RepeatBehavior="Forever" />
<ColorAnimation
To="Blue"
Storyboard.TargetName="Stop2" Storyboard.TargetProperty="Color"
BeginTime="0:0:2" Duration="0:0:2" AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Button>
</Grid>
In ScanningViewModel.cs:
class ScanningViewModel : BindableBase
{
public FrameworkElement ScanButton { get; private set; }
public ScanningViewModel()
{
ScanButton = new FrameworkElement();
}
private void SomeOtherCommand_Execute()
{
VisualStateManager.GoToElementState(this.ScanButton, "MyAnimation", false);
}
}
The goal is to add animation to a button triggered by an independent event (basically to guide the user through the app with visual clues).
I am trying to delay an animation of a custom control based on a binding value. In the example below, I’d like the animation to start 5 seconds after the “SelectedAndHit” visual state is selected. However, it doesn’t seem possible to use template binding within the VisualStateManage.
Is TemplateBinding supported within the VisualStateManager? Is there any workaround?
<local:ButtonEx x:Name="Button01" AnimationBeginTime="00:00:05" />
public TimeSpan AnimationBeginTime
{
get { return (TimeSpan)base.GetValue(ButtonEx.AnimationBeginTimeProperty); }
set { base.SetValue(ButtonEx.AnimationBeginTimeProperty, value); }
}
public static readonly DependencyProperty AnimationBeginTimeProperty =
DependencyProperty.Register("AnimationBeginTime", typeof(TimeSpan), typeof(ButtonEx), new PropertyMetadata(TimeSpan.Zero));
<Style TargetType="local:ButtonEx">
<!-- ... -->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:ButtonEx">
<Grid x:Name="Container" RenderTransformOrigin="0.5, 0.5">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="SelectedAndHit">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Border"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonBackgroundColorSelectedAndHit}" />
</ObjectAnimationUsingKeyFrames>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="GridScaleTransform"
Storyboard.TargetProperty="(ScaleTransform.ScaleX)"
To="1.2" BeginTime="{TemplateBinding AnimationBeginTime}" Duration="00:00:00.300" AutoReverse="True">
<DoubleAnimation.EasingFunction>
<ExponentialEase EasingMode="EaseIn" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
<DoubleAnimation
Storyboard.TargetName="GridScaleTransform"
Storyboard.TargetProperty="(ScaleTransform.ScaleY)"
To="1.2" BeginTime="{TemplateBinding AnimationBeginTime}" Duration="00:00:00.300" AutoReverse="True">
<DoubleAnimation.EasingFunction>
<ExponentialEase EasingMode="EaseIn" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.RenderTransform>
<ScaleTransform x:Name="GridScaleTransform" />
</Grid.RenderTransform>
<!-- ... -->
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I confirm that WinRT doesn't support Binding/TemplateBinding within a style. To workaround the issue I wrote code to manually update the BeginTime of the Storyboard. That way I had full control on when the Storyboard begins.
I would look at Interactivity. I've personally used the EventTrigger with GoToStateAction, which was enough for my purposes. From looking at MSDN it looks like you might be able to make use of TimerTrigger and GoToStateAction to create the effect you're looking for. TimerTrigger has dependency properties for setting the delay of the action to fire.
I looked on the internet but I can find this nowhere : I would like to disable the TimeHint popup that shows the current time when entering focus on a TimeUpDown control. Something like : <12:42AM>
There is no TimeHintEnabled property, nor any kind of member that seems to control this. There is a TimeHintContent property, but it is readonly and seems empty at first.
My code is really simple :
<Grid x:Name="LayoutRoot" Background="Transparent">
<toolkit:TimeUpDown Name="timeUpDown1"
Background="White"
Height="22"
MinWidth="55"
HorizontalAlignment="Left"
VerticalAlignment="Top" />
</Grid>
Maybe playing with the Template can do the trick, but I don't know how to do it...
Alright, thanks to Blend I found what I was looking for.
The Template can be easily modified by Blend, this part of the template is needed inside the xaml to hide the TimeHintPopup :
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="TimeHintStates">
<VisualState x:Name="TimeHintOpenedUp">
<Storyboard>
<ObjectAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetProperty="Visibility"
Storyboard.TargetName="TimeHintVisualElement">
<DiscreteObjectKeyFrame KeyTime="00:00:00" Value="Collapsed"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
And your TimeUpDown should refer to this template :
<toolkit:TimeUpDown Name="timeUpDown1" Background="White" Height="22" MinWidth="55" HorizontalAlignment="Left" VerticalAlignment="Top" Style="{StaticResource TimeUpDownStyle1}" />
I'm trying to get states to change with the visual state manager through code.
I am using:
Microsoft.Expression.Interactivity.Core.ExtendedVisualStateManager.GoToElementState(this.LayoutRoot, "stateRegistration", true);
But it doesn't seem to want to work, I have create an event handler and also a listener but it there's no state changed when using that code.
Can anyone help me out.
XAML CODE (Code Snippet):
<Grid x:Name="LayoutRoot" Width="897" Height="699">
<VisualStateManager.VisualStateGroups>
<VisualState x:Name="stateRegistration">
<Storyboard>
<DoubleAnimation Duration="0" To="870" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)" Storyboard.TargetName="RegisterContent" d:IsOptimized="True"/>
<DoubleAnimation Duration="0" To="880" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)" Storyboard.TargetName="HomeContent" d:IsOptimized="True"/>
<DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)" Storyboard.TargetName="btnRegRegister" d:IsOptimized="True"/>
<DoubleAnimation Duration="0" To="-10" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)" Storyboard.TargetName="btnRegRegister" d:IsOptimized="True"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
Thanks.
There is strange behavior with the VisualStateManager: its states must be situated not in the control, but in the child control.
It means, that the GoToState method should be called with the this parameter instead of the this.LayoutRoot parameter, but definitions of state groups must be situated inside the Grid:
VisualStateManager.GoToState(this, "stateRegistration", true);
I don't know where to get the ExtendedVisualStateManager class so I use the default one.
Also if any animation of the state storyboard fails - all animations are cancelled. So try this code sample with two animations, it must work:
<Grid x:Name="LayoutRoot" Width="897" Height="699">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="stateRegistration">
<Storyboard>
<DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)" Storyboard.TargetName="btnRegRegister" d:IsOptimized="True"/>
<DoubleAnimation Duration="0" To="-10" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)" Storyboard.TargetName="btnRegRegister" d:IsOptimized="True"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Button x:Name="btnRegRegister" Content="Some button" Click="btnRegRegister_Click" VerticalAlignment="Center" HorizontalAlignment="Center">
<Button.RenderTransform>
<CompositeTransform TranslateX="0" TranslateY="0" />
</Button.RenderTransform>
</Button>
</Grid>
i've been trying to deal with the following problem:
When creating a custom animations for different visual states in Expression Blend 3, which change size/opacity of multiple elements on the grid, it creates the visual state groups in the grid itself rather than in control style and defines it as CustomVisualStateManager.
<Grid x:Name="LayoutRoot" Background="White" Height="500" HorizontalAlignment="Left" VerticalAlignment="Top" Width="500">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="MyVisualStateGroup">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="00:00:00.3000000">
<VisualTransition.GeneratedEasingFunction>
<CircleEase EasingMode="EaseIn"/>
</VisualTransition.GeneratedEasingFunction>
</VisualTransition>
</VisualStateGroup.Transitions>
<VisualState x:Name="State1"/>
<VisualState x:Name="State2">
<Storyboard>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="myBox" Storyboard.TargetProperty="(FrameworkElement.Height)">
<EasingDoubleKeyFrame KeyTime="00:00:00" Value="360"/>
<!-- omitting other storyboard animations here for clarity -->
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<VisualStateManager.CustomVisualStateManager>
<ic:ExtendedVisualStateManager/>
</VisualStateManager.CustomVisualStateManager>
<!-- omitting other grid elements here for clarity -->
</Grid>
It's ok with me, but problem is, i can't switch states, in code-behind when i try
VisualStateManager.GoToState(this, "State1", true);
nothing happens, because the control itself doesn't have these visualstates defined, as shown by
VisualStateManager.GetVisualStateGroups(this);
If i try
VisualStateManager.GetVisualStateGroups(LayoutRoot);
it shows exactly what i need. But i cannot pass LayoutRoot to VisualStateManager because it needs an argument of Control type, which Grid isn't.
My question is - how can i access/ change states of this CustomVisualStateManager in code-behind?
The CustomVisualStateManager is just there when you enable FluidLayout. Unless you have layout morphing involved in your project (i.e. you are trying to use states to animate smoothly from one layout to another), you can switch it off. The presence of the custom VSM should not make any difference in the usage of VSM.
The visual state markup always is inside the top level container, so that is perfectly normal. BTW, this might be just a typo in your sample, but the code you show actually tries to set a state that has nothing in it, so that might not be the desired result.
Otherwise, calling VisualStateManager.GoToState on the UserControl should work. Here is an example I just made that works:
This is a simple Silverlight example app, with a main page and a user control that I added to the main page. The main page is really simple:
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SLStateTest"
x:Class="SLStateTest.MainPage"
Width="640" Height="480">
<Grid x:Name="LayoutRoot" Background="White">
<local:UserControl1 x:Name="TestControl" Height="100" HorizontalAlignment="Left" Margin="24,32,0,0" VerticalAlignment="Top" Width="100"/>
<Button Height="40" HorizontalAlignment="Left" Margin="192,32,0,0" VerticalAlignment="Top" Width="104" Content="State 1" Click="OnClick"/>
<Button Height="40" HorizontalAlignment="Left" Margin="192,76,0,0" VerticalAlignment="Top" Width="104" Content="State 2" Click="OnClickState2"/>
</Grid></UserControl>
There is an instance of my user control, and two buttons. We'll look at what the buttons do in a second. First let's look at the UserControl (UserControl1):
<UserControl
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"
xmlns:ic="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions"
x:Class="SLStateTest.UserControl1"
d:DesignWidth="280" d:DesignHeight="264">
<Grid x:Name="LayoutRoot" Background="#FF6FFE22">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="Test" ic:ExtendedVisualStateManager.UseFluidLayout="True">
<VisualState x:Name="State1">
<Storyboard>
<ColorAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="00:00:00" Value="#FF003AFF"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="State2">
<Storyboard>
<ColorAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="00:00:00" Value="#FFFF0202"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<VisualStateManager.CustomVisualStateManager>
<ic:ExtendedVisualStateManager/>
</VisualStateManager.CustomVisualStateManager>
</Grid></UserControl>
As you can see, there are two visual states defined in one visual state group that just set a color on the layout root of the user control.
The two buttons on the main page are wired up to event handlers that look as follows:
private void OnClick(object sender, System.Windows.RoutedEventArgs e)
{
// TODO: Add event handler implementation here.
VisualStateManager.GoToState(TestControl, "State1", true);
}
private void OnClickState2(object sender, System.Windows.RoutedEventArgs e)
{
// TODO: Add event handler implementation here.
TestControl.SetState();
}
The first one just calls VisualStateManager.GoToState on the UserControl on the page. The second one calls a function iside of the user control that does the same thing. I just used both methods to show that both options are available - you can call VSM.GoToState from the outside or the inside of a UC. The SetState() method of the user control looks as follows:
public void SetState()
{
VisualStateManager.GoToState(this, "State2", true);
}
When you run the app, the user control will first show up in its base state , which is green. When you press the State 1 button it goes to State1, which sets the UC to blue by calling VSM.GoToState() from the outside. When you press the State 2 button, it switches to red, by calling VSM from the inside.
From the snippets you posted, I can't see what is going wrong, short of the one issue that I mentioned at the beginning. However, my little sample might help you to see what is different in your case.
Hope that helps...