I have created a sliding panel in Blend for VS2013. Using two buttons I can slide the panel in and out. I want to do this with a single button. I have tried invoking the VisualStateManager.GoToState from code behind without any luck. What am I missing here?
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
xmlns:ee="http://schemas.microsoft.com/expression/2010/effects"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
x:Class="WpfApplication1.MainWindow"
Title="MainWindow" Height="350" Width="525">
<Window.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded"/>
</Window.Triggers>
<Grid>
<VisualStateManager.CustomVisualStateManager>
<ei:ExtendedVisualStateManager/>
</VisualStateManager.CustomVisualStateManager>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="SlidingPanel">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0" To="SlidePanelOut">
<ei:ExtendedVisualStateManager.TransitionEffect>
<ee:SlideInTransitionEffect SlideDirection="RightToLeft"/>
</ei:ExtendedVisualStateManager.TransitionEffect>
</VisualTransition>
<VisualTransition GeneratedDuration="0" To="SlidePanelIn">
<ei:ExtendedVisualStateManager.TransitionEffect>
<ee:SlideInTransitionEffect/>
</ei:ExtendedVisualStateManager.TransitionEffect>
</VisualTransition>
</VisualStateGroup.Transitions>
<VisualState x:Name="SlidePanelOut">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="MyStackPanel">
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)" Storyboard.TargetName="MyStackPanel">
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="SlidePanelIn">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="MyStackPanel">
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="100"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)" Storyboard.TargetName="MyStackPanel">
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<Button x:Name="button" Content="Button" Margin="0,0,397,283" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click" SourceName="button">
<ei:GoToStateAction StateName="SlidePanelIn"/>
</i:EventTrigger>
<i:EventTrigger EventName="Click">
<ei:ChangePropertyAction/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
<Button x:Name="button1" Content="Button" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Margin="160,0,0,0" Height="37" Click="button1_Click">
<!--<i:Interaction.Triggers>
<i:EventTrigger EventName="Click" SourceName="button1">
<ei:GoToStateAction StateName="SlidePanelOut"/>
</i:EventTrigger>
</i:Interaction.Triggers>-->
</Button>
<StackPanel x:Name="MyStackPanel" HorizontalAlignment="Left" Height="278" VerticalAlignment="Top" Width="100" Background="#FFDC1717" RenderTransformOrigin="0.5,0.5" Margin="-100,42,0,0">
<StackPanel.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</StackPanel.RenderTransform>
<Button Content="Button"/>
<Button Content="Button"/>
<Button Content="Button"/>
</StackPanel>
</Grid>
</Window>
private void button1_Click(object sender, RoutedEventArgs e)
{
VisualState vs = SlidingPanel.CurrentState;
if (vs.Name == "SlidePanelIn")
{
VisualStateManager.GoToState(MyStackPanel, SlidePanelOut.Name, true);
}
}
Any and all help appreciated!
TIA,
Doug
You will make things simpler if you use a ToggleButton as your single Button. Then you can use the Checked and Unchecked events to trigger changes to your VisualTransition states:
<ToggleButton x:Name="button" Content="Button" Margin="0,0,397,283" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="Checked" SourceName="button">
<ei:GoToStateAction StateName="SlidePanelIn"/>
</i:EventTrigger>
<i:EventTrigger EventName="Unchecked">
<ei:GoToStateAction StateName="SlidePanelOut"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ToggleButton>
Related
This question already has answers here:
Detect mouse directly over border in WPF
(2 answers)
Closed 8 years ago.
I build a small control with a panel of two buttons. When I hover the control I want to show the panel and hide it when I leave. Everything works great, but I have one bug. When I move the cursor from the TextBlock to the Image my Storyboard run again. I dont understand why because both of them are inside the control. I try to add a Border to wrap the control, but it didnt work.
<UserControl.Resources>
<Storyboard x:Key="Show">
<DoubleAnimationUsingKeyFrames
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)"
Storyboard.TargetName="QuickPanel">
<EasingDoubleKeyFrame KeyTime="0" Value="18"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="Hide">
<DoubleAnimationUsingKeyFrames
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)"
Storyboard.TargetName="QuickPanel">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="18"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</UserControl.Resources>
<UserControl.Triggers>
<EventTrigger RoutedEvent="Border.MouseEnter">
<BeginStoryboard Storyboard="{StaticResource Show}"/>
</EventTrigger>
<EventTrigger RoutedEvent="Border.MouseLeave">
<BeginStoryboard Storyboard="{StaticResource Hide}"/>
</EventTrigger>
</UserControl.Triggers>
<Border Width="144" Height="36" ClipToBounds="True" BorderThickness="0">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Image Source="http://www.streamplay.fr/thumb/fanart/3000/3000/1321396.jpg"
VerticalAlignment="Center" HorizontalAlignment="Center" Margin="2"
Stretch="UniformToFill" Height="34" Width="34"/>
<Grid Grid.Column="1">
<StackPanel VerticalAlignment="Center" Margin="6,0,0,0">
<TextBlock FontSize="12" FontWeight="DemiBold">Sample Title</TextBlock>
<TextBlock FontSize="10" Text="{Binding Title, Mode=TwoWay}"></TextBlock>
</StackPanel>
</Grid>
<StackPanel x:Name="QuickPanel" Grid.Column="1" Width="18" HorizontalAlignment="Right" RenderTransformOrigin="0.5,0.5">
<StackPanel.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform X="18"/>
</TransformGroup>
</StackPanel.RenderTransform>
<Button x:Name="button" Height="18" Content="p" IsDefault="True" />
<Button x:Name="button1" Height="18" Content="k" />
</StackPanel>
</Grid>
</Border>
Any idea how to change this ?
You need to set a background to your Border element UI:
Border Background="Transparent" ...
If you don't set the background, the space between image and textblock is your parent window.
I'm trying to change the height of a WPF grid from 0 to Auto using Storyboard. I know I can't do it without tricking, so I tried to change the MaxHeight Value, using Databinding in the Storyboard. But I can't make it works (height is always equals to 0). Here is the code I use :
The two visualstates :
<VisualState x:Name="SelectionMode">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="CurrentToolGrid" Storyboard.TargetProperty="(FrameworkElement.MaxHeight)">
<EasingDoubleKeyFrame KeyTime="0" Value="0" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="EditionMode">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="CurrentToolGrid" Storyboard.TargetProperty="(FrameworkElement.MaxHeight)">
<EasingDoubleKeyFrame KeyTime="0" Value="{Binding ElementName=CurrentToolGrid, Path=ActualHeight}" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
Here is my grid definition :
<Grid x:Name="CurrentToolGrid" Background="#FFDEDEDE" Grid.Row="1" Height="Auto">
[... some controls that extends the grid's height ...]
</Grid>
Why the height of the CurrentToolGrid is always 0 ?
Thanks for helping me :)
Please refer to following code, I use TranslateTransform instead of MaxWidth, it make scense for Slide scenario.The key to impl this is StoryBoard should define in resource, then storyboard can find the specify control which binding in doubleanimation.
<Window x:Class="SlideUpWPFTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
x:Name="Window"
Title="MainWindow"
Width="640"
Height="480">
<Window.Resources>
<Storyboard x:Key="sb1">
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="grdContent" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
<EasingDoubleKeyFrame KeyTime="0" Value="{Binding ElementName=grdContent, Path=ActualWidth}" />
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="0" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="sb2">
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="grdContent" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
<EasingDoubleKeyFrame KeyTime="0" Value="0" />
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="{Binding ElementName=grdContent, Path=ActualWidth}" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Grid x:Name="LayoutRoot" RenderTransformOrigin="0.5,0.5">
<Grid.RowDefinitions>
<RowDefinition Height="35" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Grid.RenderTransform>
<TransformGroup>
<ScaleTransform />
<SkewTransform />
<RotateTransform />
<TranslateTransform />
</TransformGroup>
</Grid.RenderTransform>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="VisualStateGroup">
<VisualState x:Name="EditMode" Storyboard="{StaticResource sb1}" />
<VisualState x:Name="SelectionMode" Storyboard="{StaticResource sb2}" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
<Button Content="Enter Edit Mode">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ei:GoToStateAction StateName="EditMode" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
<Button Content="Enter Selected Mode">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ei:GoToStateAction StateName="SelectionMode" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</StackPanel>
<Grid x:Name="grdContent"
Grid.Row="1"
RenderTransformOrigin="0.5,0.5">
<Grid.RenderTransform>
<TransformGroup>
<ScaleTransform />
<SkewTransform />
<RotateTransform />
<TranslateTransform />
</TransformGroup>
</Grid.RenderTransform>
<!-- some content -->
<Rectangle Height="65" Fill="LightBlue" />
</Grid>
</Grid>
</Window>
In Excel, when you press Ctrl+C, the current cell is surrounded by a rectangle with broken line seemingly running around. Any tip on how to make it in WPF?
What you're looking for is usually called a "Marching Ants Border". There are already a few implementations out there for WPF.
Here is one from Patric Johansson's blog and another from codeproject
Added main code from CodeProject for future references:
<Window.Resources>
<Storyboard x:Key="MarchingAnts">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="rectangle"
Storyboard.TargetProperty="(Shape.StrokeDashOffset)"
RepeatBehavior="Forever">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.5000000"
Value="10"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource MarchingAnts}"/>
</EventTrigger>
</Window.Triggers>
<Grid x:Name="LayoutRoot">
<Canvas x:Name="canvas" Background="#FF262626">
<Rectangle Fill="#14FFFFFF" StrokeDashArray="5"
Stroke="#FFFFFFFF"
x:Name="rectangle" Width="50" Height="50"
StrokeDashOffset="0" StrokeThickness="1"
RadiusX="0" RadiusY="0"
Canvas.Left="0" Canvas.Top="0"/>
<TextBlock Width="Auto" Height="Auto"
FontFamily="Century Gothic"
FontSize="48" Foreground="#FF5B5B5B"
Text="MARCHING ANTS" TextWrapping="Wrap"
Canvas.Top="182" Canvas.Left="79"/>
</Canvas>
</Grid>
I want the items added to my ItemsControl to animate the height when they're added. The following sample, using triggers, did the job, but I couldn't get it to work with a non-fixed height for the items (50 in this case).
<ItemsControl ItemsSource="{Binding Notifications}">
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type Notifications1:Notification}">
<Button x:Name="ItemButton"
ClipToBounds="True"
Height="0">
<Button.Template>
<ControlTemplate>
<Notifications:NotificationTile />
</ControlTemplate>
</Button.Template>
</Button>
<DataTemplate.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded"
SourceName="ItemButton">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Height"
Storyboard.TargetName="ItemButton"
Duration="0:0:0.5"
To="50" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ItemsControl.Resources>
I then tried to use the VisualStateManager to perform the animations, so the tiles would grow to whatever height they required. In the example below, the items are added at the correct size, but no animation is performed. I assume the EventTrigger isn't even being fired?
Any ideas much appreciated!
<ItemsControl ItemsSource="{Binding Notifications}"
Width="230"
ScrollViewer.HorizontalScrollBarVisibility="Hidden"
HorizontalContentAlignment="Stretch">
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type Notifications1:Notification}">
<Button x:Name="ItemButton"
ClipToBounds="True"
Command="{Binding DataContext.ItemClicked, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"
CommandParameter="{Binding}"
Visibility="{Binding IsVisible, Converter={StaticResource boolToVisibilityConverter}}">
<Button.Template>
<ControlTemplate>
<Notifications:NotificationTile />
</ControlTemplate>
</Button.Template>
<VisualStateManager.CustomVisualStateManager>
<is:ExtendedVisualStateManager />
</VisualStateManager.CustomVisualStateManager>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup is:ExtendedVisualStateManager.UseFluidLayout="True">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:2" />
</VisualStateGroup.Transitions>
<VisualState x:Name="Collapsed">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(FrameworkElement.Height)"
Storyboard.TargetName="ItemButton"
Duration="0"
To="0" />
</Storyboard>
</VisualState>
<VisualState x:Name="Expanded">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Height)"
Storyboard.TargetName="ItemButton">
<DiscreteDoubleKeyFrame KeyTime="0"
Value="NaN" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<i:Interaction.Triggers>
<i:EventTrigger SourceName="ItemButton"
EventName="(FrameworkElement.Loaded)">
<is:GoToStateAction StateName="Expanded" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</DataTemplate>
</ItemsControl.Resources>
Maybe this is a bit off-topic, sorry for that. I'm not sure I understood your question fully.
Anyway, it generally cannot be recommended to have an animation with only "To", as the "From" is originally set to a Double.NaN, and the DoubleAnimation doesn't work in this case.
I created a User Control that has an image, text, and description. I would like to animate it to display a border when user hovers over.
I have done that, but the animation fires off on each element of the control so the border keeps on appearing and disappearing again.
Here is the code for my control.
Please help and thank you in advance!
<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"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
mc:Ignorable="d"
x:Class="SilverlightApplication2.CommandLinks"
d:DesignWidth="640" d:DesignHeight="480" Width="280" Cursor="Hand">
<UserControl.Resources>
<Storyboard x:Name="CommandLinksMounseOver">
<ColorAnimation Duration="0:0:0.1" To="#FFB0D0E0" Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)" Storyboard.TargetName="brdBorder" d:IsOptimized="True"/>
<DoubleAnimation Duration="0:0:0.1" To="1" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)" Storyboard.TargetName="brdBorder" d:IsOptimized="True"/>
<DoubleAnimation Duration="0:0:0.1" To="-1" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)" Storyboard.TargetName="brdBorder" d:IsOptimized="True"/>
</Storyboard>
<Storyboard x:Name="CommandLinksMouseOut">
<ColorAnimation Duration="0:0:0.1" To="#FFD9E8F0" Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)" Storyboard.TargetName="brdBorder" d:IsOptimized="True"/>
<DoubleAnimation Duration="0:0:0.1" To="-1" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)" Storyboard.TargetName="brdBorder" d:IsOptimized="True"/>
<DoubleAnimation Duration="0:0:0.1" To="1" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)" Storyboard.TargetName="brdBorder" d:IsOptimized="True"/>
</Storyboard>
</UserControl.Resources>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter">
<ei:ControlStoryboardAction x:Name="OnMouseOut" Storyboard="{StaticResource CommandLinksMouseOut}"/>
<ei:ControlStoryboardAction x:Name="OnMouseOver" Storyboard="{StaticResource CommandLinksMounseOver}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<Grid x:Name="LayoutRoot">
<Border x:Name="brdBorder" Margin="0" CornerRadius="3" BorderThickness="1" Padding="8" BorderBrush="#00B3D1E1" RenderTransformOrigin="0.5,0.5">
<Border.RenderTransform>
<CompositeTransform/>
</Border.RenderTransform>
<Grid>
<Image x:Name="imgIcon" HorizontalAlignment="Left" Width="32" Margin="0" Source="Universal Binary.png" VerticalAlignment="Top" RenderTransformOrigin="0.5,0.5" Height="32">
<Image.RenderTransform>
<CompositeTransform/>
</Image.RenderTransform>
</Image>
<TextBlock x:Name="txtMainInstruction" TextWrapping="Wrap" Text="Main instruction text" VerticalAlignment="Top" Padding="0" Foreground="#FF2C5A88" FontSize="13.333" FontFamily="Verdana" Margin="40,0,0,0" RenderTransformOrigin="0.5,0.5">
<TextBlock.RenderTransform>
<CompositeTransform/>
</TextBlock.RenderTransform>
</TextBlock>
<TextBlock x:Name="txtDescription" TextWrapping="Wrap" Text="Enter the description here if needed" VerticalAlignment="Top" Foreground="#FF666666" FontSize="12" FontFamily="Verdana" Margin="40,20,0,0" RenderTransformOrigin="0.5,0.5">
<TextBlock.RenderTransform>
<CompositeTransform/>
</TextBlock.RenderTransform>
</TextBlock>
</Grid>
</Border>
</Grid>
Along with setting a transparent background (I put it on the brdBorder element) as already suggested there is a problem with your triggers. They should look like this:
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeave">
<ei:ControlStoryboardAction x:Name="OnMouseOut" Storyboard="{StaticResource CommandLinksMouseOut}"/>
</i:EventTrigger>
<i:EventTrigger EventName="MouseEnter">
<ei:ControlStoryboardAction x:Name="OnMouseOver" Storyboard="{StaticResource CommandLinksMounseOver}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
The control has no background. Therefore only the text and the image are hit test visible. Try Background="#00000000" (transparent) on the LayoutRoot.