I would like to add a fade in/out effect to some text (aka, a WPF Run object). I don't want it to toggle Bold/notBold all at once. I want it to animate between Bold and normal. Is this possible?
I don't think you can animate between Fontweights, as those are like fixed values that don't have "intermediate" states. I think the best bet is having 2 Textblocks (a Normal one and a Bold one with the same Text) and then animating Opacity of both, making the normal one fade out and the Bold one fade in. This way it will seem like the font is "transitioning" from normal to bold in an animated fashion.
<Control>
<Control.Template>
<ControlTemplate>
<DockPanel>
<ToggleButton x:Name="btn" Content="IsBold"/>
<Grid Width="200">
<TextBlock Text="Transition" x:Name="normal" TextAlignment="Center"/>
<TextBlock Text="Transition" FontWeight="Bold" Opacity="0" x:Name="bold" TextAlignment="Center"/>
</Grid>
</DockPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" SourceName="btn" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard Duration="00:00:01">
<DoubleAnimation Storyboard.TargetName="normal" Storyboard.TargetProperty="Opacity" To="0"/>
<DoubleAnimation Storyboard.TargetName="bold" Storyboard.TargetProperty="Opacity" To="1"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard Duration="00:00:01">
<DoubleAnimation Storyboard.TargetName="normal" Storyboard.TargetProperty="Opacity" To="1"/>
<DoubleAnimation Storyboard.TargetName="bold" Storyboard.TargetProperty="Opacity" To="0"/>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Control.Template>
</Control>
Related
I've trying to create a navigation panel on the left of my app, I have several ListViews stacked on top of each other, with an invisible ToggleButton on the first item of each list. Then when these ToggleButtons are switched I want to trigger an event on the other ListViews.
I.e. change the height of all other ListViews to just view the first item;
Setter TargetName="ClientItems" Property="Height" Value="40"
And also switch the value of the other ToggleButtons so only one or none ToggleButtons are checked.
Setter TargetName="ClientsTglBtn" Value="ToggleButton.Checked"
<ToggleButton x:Name="ProjectsTglBtn"
Width="190"
Height="40"
VerticalAlignment="Top"
BorderThickness="0"
Background="Transparent"
Style="{StaticResource ToggleButtonStyle}">
<ToggleButton.Triggers>
<EventTrigger RoutedEvent="ToggleButton.Unchecked">
<BeginStoryboard>
<Storyboard x:Name="HideProjectItems">
<DoubleAnimation
Storyboard.TargetName="ProjectItems"
Storyboard.TargetProperty="Height"
BeginTime="0:0:0:0"
From="160" To="40"
Duration="0:0:0:0.25">
</DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="ToggleButton.Checked">
<Setter TargetName="ClientItems" Property="Height" Value="40"/>
<Setter TargetName="ClientsTglBtn" Value="ToggleButton.Checked"/>
<BeginStoryboard>
<Storyboard x:Name="ShowProjectItems">
<DoubleAnimation
Storyboard.TargetName="ProjectItems"
Storyboard.TargetProperty="Height"
BeginTime="0:0:0:0"
From="40" To="160"
Duration="0:0:0:0.25">
</DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ToggleButton.Triggers>
</ToggleButton>
I have a Style Trigger to expand an image when the mouse is over it (actually a border around the image) and contract when it moves off. This is done via an animated scale transform.
However if the mouse moves off the expanding image but is still within the area it is expanding into, before the mouse over animation has completed, the expand and contract animations get constantly triggered causing the image to flicker between expanding and contracting.
<Setter Property="RenderTransform">
<Setter.Value>
<ScaleTransform/>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ThicknessAnimation Duration="0:0:0.5" To="2.5" Storyboard.TargetProperty="BorderThickness" />
<DoubleAnimation Storyboard.TargetProperty="RenderTransform.ScaleX" From="1" To="1.2" Duration="0:0:0.5" AccelerationRatio="0.2" DecelerationRatio="0.4"/>
<DoubleAnimation Storyboard.TargetProperty="RenderTransform.ScaleY" From="1" To="1.2" Duration="0:0:0.5" AccelerationRatio="0.2" DecelerationRatio="0.4"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ThicknessAnimation Duration="0:0:0.5" To="1.5" Storyboard.TargetProperty="BorderThickness" />
<DoubleAnimation Storyboard.TargetProperty="RenderTransform.ScaleX" From="1.2" To="1" Duration="0:0:0.5" AccelerationRatio="0.2" DecelerationRatio="0.4"/>
<DoubleAnimation Storyboard.TargetProperty="RenderTransform.ScaleY" From="1.2" To="1" Duration="0:0:0.5" AccelerationRatio="0.2" DecelerationRatio="0.4"/>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
<Border BorderBrush="{Binding IsSelected, Converter={StaticResource BorderColourConverter}, Mode=OneWay}"
BorderThickness="1.5" Style="{StaticResource ThumbnailScale}">
<Border.Background>
<SolidColorBrush Color="Transparent"/>
</Border.Background>
<Image Source="{Binding ImageSource}" Width="{Binding ThumbnailWidth, Mode=OneWay}"
Height="{Binding ThumbnailHeight, Mode=OneWay}" Stretch="Uniform"/>
</Border>
Is there some way to stop the recursive triggering of the animations and so stop the continual change in the image size?
Just after posting the question I looked at a slow motion video of what was happening and figured out what was happening and how to fix it.
The problem was with the second (and subsequent) invocation of the animation's start point.
They assumed that the previous animation had finished when it hadn't. So by removing the "From" clause in the animations they started from their current scaling and this solved the problem.
SliderMenu in Youtube
I can't do something similar to this video, the animation doesn't stop and the menu always flashes. Here's my XAML:
<StackPanel.Style>
<Style TargetType="StackPanel">
<Style.Triggers>
<EventTrigger RoutedEvent="MouseEnter">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<ThicknessAnimation Storyboard.TargetProperty="Margin"
From="-70,0,0,0" To="15,0,15,0"
DecelerationRatio=".8" Duration="0:0:0.7"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeave">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<ThicknessAnimation Storyboard.TargetProperty="Margin"
From="15,0,15,0" To="-70,0,0,0"
DecelerationRatio=".8" Duration="0:0:0.7"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
What's the problem with it?
The flickering is happening because as soon as the StackPanel starts animating, it moves itself out of the way (of the mouse cursor), causing the other animation to start. I don't see you full code, so here are a couple of pointers to improve your code.
Make sure the entire menu is hittest-visible (e.g. by setting a background)
Don't use two triggers, use one trigger with enter and exit-triggers
Avoid the margin on the left - it can cause the same kind of flickering again.
<StackPanel Background="Blue" Width="100" HorizontalAlignment="Left">
<StackPanel.Style>
<Style TargetType="StackPanel">
<Setter Property="Margin" Value="-70,0,0,0"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ThicknessAnimation Storyboard.TargetProperty="Margin"
From="-70,0,0,0" To="0,0,0,0"
DecelerationRatio=".8" Duration="0:0:0.7"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ThicknessAnimation Storyboard.TargetProperty="Margin"
From="0,0,0,0" To="-70,0,0,0"
DecelerationRatio=".8" Duration="0:0:0.7"/>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<Button Width="100" Height="25"></Button>
</StackPanel>
Result:
I have a list view that is being populated with wrap panels through my binding. My code currently will animate the opacity on MouseEnter (opacity up to 1.0) and MouseLeave (opacity down to {Binding PanelOpacity}) just fine. However, when I select a different wrap panel, I need the storyboard for MouseLeave to fire to reduce the opacity.
Snippet:
<ListView.ItemTemplate>
<DataTemplate>
<WrapPanel x:Name="panelObject" Orientation="Horizontal" Margin="5,7">
<WrapPanel.InputBindings>
<MouseBinding MouseAction="LeftClick"
Command="{Binding DataContext.GridClickCmd, RelativeSource={RelativeSource AncestorType=Grid}}"
CommandParameter="{Binding Server}"/>
</WrapPanel.InputBindings>
<WrapPanel.Style>
<Style TargetType="{x:Type WrapPanel}">
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Red" />
</Style.Resources>
<Setter Property="Opacity" Value="{Binding PanelOpacity}" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Opacity" Value="1.0" />
</Trigger>
</Style.Triggers>
</Style>
</WrapPanel.Style>
<WrapPanel.Triggers>
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard>
<Storyboard x:Name="FadeIn">
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
To="1.0" Duration="0:0:0.2" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeave">
<BeginStoryboard>
<Storyboard x:Name="FadeOut">
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
To="{Binding PanelOpacity}" Duration="0:0:0.2" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="SourceUpdated">
<BeginStoryboard>
<Storyboard x:Name="ChangeSelection">
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
To="{Binding PanelOpacity}" Duration="0:0:0.2" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</WrapPanel.Triggers>
</WrapPanel>
</DataTemplate>
</ListView.ItemTemplate>
I've tried using a few different Routed Events and none of them seem to fire when a different wrap panel is clicked.
Last thing I tried was this:
<EventTrigger RoutedEvent="SourceUpdated">
<BeginStoryboard>
<Storyboard x:Name="ChangeSelection">
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
To="{Binding PanelOpacity}" Duration="0:0:0.2" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
Edit: I've got this in my C#. It works fine currently, without animation:
_viewModel.MainPanel.ToList().Find(x => x.Server == (string)parameter).PanelOpacity = 1.0;
_viewModel.MainPanel.ToList().FindAll(x => x.Server != (string)parameter).ForEach(x => x.PanelOpacity = 0.5);
Second Edit: Added more tags to show location of code.
Final Edit: full ItemTemplate code added.
I'm developing a WPF Application for Touch Devices. I want a behaviour like in Android Browser, if you focus a TextBox the screen 'zooms' in so you only see the TextBox and the virtual Keyboard.
I have already tried Scaling the TextBox and setting the Position if it has Focus but that doesn't work right. If somebody could point me in the right direction i would appreciate that.
you can achieve this function from this code
<TextBox Background="LightGreen" Width="100" Height="100" BorderBrush="Green">
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ThicknessAnimation Duration="0:0:0.400" To="3" Storyboard.TargetProperty="BorderThickness" />
<DoubleAnimation Duration="0:0:0.300" To="125" Storyboard.TargetProperty="Height" />
<DoubleAnimation Duration="0:0:0.300" To="125" Storyboard.TargetProperty="Width" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ThicknessAnimation Duration="0:0:0.250" To="0" Storyboard.TargetProperty="BorderThickness" />
<DoubleAnimation Duration="0:0:0.150" To="100" Storyboard.TargetProperty="Height" />
<DoubleAnimation Duration="0:0:0.150" To="100" Storyboard.TargetProperty="Width" />
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>