WPF XAML Togglebutton trigger event on different target - c#

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>

Related

Style Triggers being recursivly applied

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.

Animate when another wrap panel is clicked

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.

How to specify a target for animation?

Before you read this question, please see this
Now I have the storyboard defined in the user control resources and it gets triggered it on an event that is defined in ViewModel:
<UserControl.Resources>
<Storyboard x:Key="Storyboard2">
<DoubleAnimation Storyboard.TargetName="Btn_Import" Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:2"/>
<DoubleAnimation Storyboard.TargetName="Studio" Storyboard.TargetProperty="Opacity" From="0" To="{Binding StudioOpacityValue}" Duration="0:0:2"/>
<DoubleAnimation Storyboard.TargetName="StudioTranslateLeftToRight" Storyboard.TargetProperty="X" By="{Binding StudioStartingPointWidth}" Duration="0:0:2">
<DoubleAnimation.EasingFunction>
<CubicEase EasingMode="EaseInOut"/>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
<DoubleAnimation Storyboard.TargetName="Animation" Storyboard.TargetProperty="Opacity" From="0" To="{Binding AnimationOpacityValue}" Duration="0:0:2"/>
<DoubleAnimation Storyboard.TargetName="Record" Storyboard.TargetProperty="Opacity" From="0" To="{Binding RecordOpacityValue}" Duration="0:0:2"/>
<DoubleAnimation Storyboard.TargetName="Info" Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:2"/>
<DoubleAnimation Storyboard.TargetName="textframe_image" Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:2"/>
<local:CommandFakeAnimation Command="{Binding Path=MainButtonClickedCommand, Mode=OneWay}" CommandParameter="Hide" Storyboard.TargetProperty="Opacity" Duration="0:0:0"/>
</Storyboard>
</UserControl.Resources>
and then I have an event that trigers the storyboard:
<i:Interaction.Triggers>
<i:EventTrigger EventName="FadeInMainButtonsAfterStudio" SourceObject="{Binding Mode=OneWay}">
<ei:ControlStoryboardAction Storyboard="{StaticResource Storyboard2}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
and the control that I want to apply the animation to is:
<Button x:Name ="Studio" Grid.Row="33" Grid.Column="57" Grid.ColumnSpan="36" Grid.RowSpan="36" IsEnabled="{Binding IsStudioEnabled}" Opacity="{Binding StudioOpacityValue}" Command="{Binding MainButtonClickedCommand}" CommandParameter="Show">
<Button.Template>
<ControlTemplate>
<Grid RenderTransformOrigin="0.5,0.5" x:Name="bg">
<Image x:Name ="studio_image" Source="{Binding StudioBtnBaseImagePath}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="studio_image" Property="Source" Value="{Binding StudioBtnOverImagePath}" />
</Trigger>
<Trigger Property="ButtonBase.IsPressed" Value ="True">
<Setter TargetName="bg" Property="RenderTransform">
<Setter.Value>
<ScaleTransform ScaleX="0.9" ScaleY="0.9"/>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
<Button.RenderTransform>
<TransformGroup>
<TranslateTransform x:Name="StudioTranslateLeftToRight" X="0"/>
</TransformGroup>
</Button.RenderTransform>
</Button>
but I get the following runtime error:
Additional information: No target was specified for
'MainMenu.DummyAnimations.CommandFakeAnimation'
What could be the problem with this?
As clearly described in the error you are getting, you have not provided Storyboard.TargetName for your custom Animation local:CommandFakeAnimation

possible to pulse text by smoothly changing fontweight in WPF?

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>

Error while increasing Opacity property using DoubleAnimation

I have a style for a ListViewItem control:
<EventTrigger RoutedEvent="ListViewItem.MouseEnter">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="BitmapEffect.Opacity"
From="0.0" To="1.0" Duration="0:0:0.5" AutoReverse="False" SpeedRatio="2" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="ListViewItem.MouseLeave">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="BitmapEffect.Opacity"
From="1.0" To="0.0" Duration="0:0:0.5" AutoReverse="False" SpeedRatio="2" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
I want to when mouse is over a ListViewItem, border of item appearing slowly and when mouse leave it, border effect disappear,
But i get this error when mouse goes to leave item:
Cannot resolve all property references in the property path 'BitmapEffect.Opacity'. Verify
that applicable objects support the properties.
Note that when i use only first EventTrigger which routed to ListViewItem.MouseEnter, program works correct! but it has not a good view!
I'm using OuterGlowBitmapEffect!
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="BitmapEffect">
<Setter.Value>
<OuterGlowBitmapEffect GlowColor="SkyBlue" GlowSize="20" />
</Setter.Value>
</Setter>
<Setter Property="Foreground" Value="Black" />
</Trigger>
I was trying with BitmapEffect, it is working fine as your above code.
<Style x:Key="ListBoxItemStyle1" TargetType="{x:Type ListBoxItem}">
<Setter Property="BitmapEffect">
<Setter.Value>
<OuterGlowBitmapEffect GlowColor="Blue" GlowSize="5" />
</Setter.Value>
</Setter>
<Style.Triggers>
<EventTrigger RoutedEvent="ListViewItem.MouseEnter">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="BitmapEffect.Opacity"
From="0.0" To="1.0" Duration="0:0:0.5" AutoReverse="False" SpeedRatio="2" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
<EventTrigger RoutedEvent="ListViewItem.MouseLeave">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="BitmapEffect.Opacity"
From="1.0" To="0.0" Duration="0:0:0.5" AutoReverse="False" SpeedRatio="2" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
Added Whole sample.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Custom="http://schemas.microsoft.com/wpf/2008/toolkit"
xmlns:uc="clr-namespace:WpfApplication10"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Class="WpfApplication10.Window1"
x:Name="Window"
Title="Window1" mc:Ignorable="d">
<Window.Resources>
<DataTemplate x:Key="ItemTemplate1">
<StackPanel>
<TextBlock Text="{Binding Property1}"/>
<Image Source="{Binding Property2}" HorizontalAlignment="Left" Height="64" Width="64"/>
</StackPanel>
</DataTemplate>
<Style x:Key="ListBoxItemStyle1" TargetType="{x:Type ListBoxItem}">
<Setter Property="BitmapEffect">
<Setter.Value>
<OuterGlowBitmapEffect GlowColor="Blue" GlowSize="5" />
</Setter.Value>
</Setter>
<Style.Triggers>
<EventTrigger RoutedEvent="ListViewItem.MouseEnter">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="BitmapEffect.Opacity"
From="0.0" To="1.0" Duration="0:0:0.5" AutoReverse="False" SpeedRatio="2" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
<EventTrigger RoutedEvent="ListViewItem.MouseLeave">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="BitmapEffect.Opacity"
From="1.0" To="0.0" Duration="0:0:0.5" AutoReverse="False" SpeedRatio="2" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid DataContext="{Binding Source={StaticResource SampleDataSource1}}">
<ListBox DataContext="{Binding Source={StaticResource SampleDataSource3}}"
ItemTemplate="{DynamicResource ItemTemplate1}" ItemsSource="{Binding Collection}"
ItemContainerStyle="{DynamicResource ListBoxItemStyle1}" >
</ListBox>
</Grid>

Categories

Resources