WPF - Setting usercontrol width using triggers and mouseenter event - wpf

I have a wrap panel full of usercontrols. When I hover the mouse over a usercontrol I want it to expand to show more details.
Some stripped down sample code:
<UserControl x:Class="WPFTestBed.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="300" Width="300">
<UserControl.Resources>
</UserControl.Resources>
<UserControl.Triggers>
<EventTrigger RoutedEvent="Mouse.MouseEnter">
<EventTrigger.Actions>
<Setter TargetName="WPFTestBed.UserControl1" Property="Control.Width" Value="200"/>
</EventTrigger.Actions>
</EventTrigger>
</UserControl.Triggers>
<Grid Height="95" Width="123">
<Button Height="23" HorizontalAlignment="Left" Margin="17,30,0,0" Name="button1" VerticalAlignment="Top" Width="75">Button</Button>
</Grid>
</UserControl>
I would appreciate it if someone could point out where I'm going wrong, and set me down the correct path.
Ideally, I want the usercontrol to delay for x seconds when there is a mouseover, before expanding and showing the extra details.

Here is a solution (tested):
Keep in mind that you have to set a Width manually on the UserControl for this to work.
Then add this to your UserControl's body:
<UserControl.Style>
<Style>
<Style.Triggers>
<EventTrigger RoutedEvent="Mouse.MouseEnter">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard BeginTime="0:0:4.0" Storyboard.TargetProperty="Width">
<DoubleAnimation To="200" Duration="0:0:1.0"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
</UserControl.Style>
It will start after 4 seconds, then animate the width from its current value to 200, over 1 second.

I've managed to get a bit further with what I want:
<UserControl x:Class="WPFTestBed.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="200" Width="170">
<UserControl.Resources>
<Storyboard x:Key="ExpandDisplay">
<DoubleAnimation Storyboard.TargetProperty="(UserControl.Width)"
From="200" To="380" Duration="0:0:0.25" AutoReverse="False"/>
<DoubleAnimation Storyboard.TargetProperty="(Border.Width)"
Storyboard.TargetName="mainBorder"
From="190" To="370" Duration="0:0:0.25" AutoReverse="False"/>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="button2"
Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="CollapseDisplay">
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="button2"
Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame Value="{x:Static Visibility.Collapsed}"/>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimation Storyboard.TargetProperty="(UserControl.Width)"
From="380" To="200" Duration="0:0:0.25" AutoReverse="False"/>
<DoubleAnimation Storyboard.TargetProperty="(Border.Width)"
Storyboard.TargetName="mainBorder"
From="370" To="190" Duration="0:0:0.25" AutoReverse="False"/>
</Storyboard>
</UserControl.Resources>
<UserControl.Triggers>
<EventTrigger RoutedEvent="Mouse.MouseDown">
<BeginStoryboard Storyboard="{StaticResource ExpandDisplay}"/>
</EventTrigger>
<EventTrigger RoutedEvent="Button.Click" SourceName="button2">
<BeginStoryboard Storyboard="{StaticResource CollapseDisplay}"/>
</EventTrigger>
</UserControl.Triggers>
<Border Name="mainBorder" Height="190" Width="160" Background="Black" CornerRadius="20,20,20,20">
<Border.BitmapEffect>
<DropShadowBitmapEffect Color="Black" Direction="320" ShadowDepth="10" Opacity=".5"
Softness="9"/>
</Border.BitmapEffect>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Button Grid.Row="0" Height="23" Width="75" VerticalAlignment="Center" HorizontalAlignment="Center" Name="button1" >Details</Button>
<Button Grid.Row="1" Height="23" Width="23" VerticalAlignment="Center" HorizontalAlignment="Center" Name="button2" Visibility="Collapsed">-</Button>
</Grid>
</Border>
</UserControl>
This expands the usercontrol when I click, rather than mouseover, as I couldn't find a satisfactory way to wait for a second before beginning. I could delay the start and cancel on a mouseleave but this also cancelled the expand whenever the mouseleave was called.
I have a button to collapse the usercontrol, but I would prefer to switch which storyboard the usercontrol onclick event calls, can this be done?

Related

Animate an image inside of a tooltip of a button

For the application I am working on, I need an animation.
The problem is, that the animation is in a tooltip.
So I have a button and whenever I move over the button the tooltip comes up. The tooltip shows a short information text (Textblock) and after about two seconds he shall expand and show an image.
Since I am an XAML-only developer, which means I have no clue about C# and therefore I have no idea about binding to a viewmodel, I am looking for a way to do this with triggers and storyboards.
I have already achieved that effect with an Event Trigger, who reacts to the Routed Event Loaded. The problem is, that this works "only" once, when the Tooltip is loaded the first time.
Here is my code:
<Button Width="100" Height="100">
<Button.ToolTip>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="Here is some text!"></TextBlock>
<Image Grid.Row="1" Visibility="Collapsed" Source="MyPicture.png">
<Image.Style>
<Style TargetType="Image">
<Style.Triggers>
<EventTrigger RoutedEvent="Loaded">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetProperty="Visibility"
Duration="0"
BeginTime="0:0:2">
<DiscreteObjectKeyFrame Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</Grid>
</Button.ToolTip>
</Button>
Is there a better Routed Event than "Loaded" or do I have to make my own Routed Event? Can I link the Event to the Button, like "When Button IsMouseOver is true do this with the image"?
Or is there a complete better way?
Nevertheless, solutions regarding a way with C# are also welcomed.
Thanks for any advices,
Gerrit
A DataTrigger on the ToolTip's Visibility, with Enter and Exit actions should work. Note the explicit <ToolTip>...</ToolTip>
<Button Width="100" Height="100">
<Button.ToolTip>
<ToolTip>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="Here is some text!"></TextBlock>
<Image Grid.Row="1" Visibility="Collapsed" Source="MyPicture.png">
<Image.Style>
<Style TargetType="Image">
<Style.Triggers>
<DataTrigger Binding="{Binding IsVisible, RelativeSource={RelativeSource AncestorType=ToolTip}}"
Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetProperty="Visibility"
Duration="0"
BeginTime="0:0:2">
<DiscreteObjectKeyFrame Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetProperty="Visibility"
Duration="0">
<DiscreteObjectKeyFrame Value="{x:Static Visibility.Collapsed}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</Grid>
</ToolTip>
</Button.ToolTip>
</Button>
Since you do not set the FillBehavior property in your animation, it is set to HoldEnd (i.e. the animation holds its value after it reaches the end of its active period). So you need just an "opposite" animation to reset the Visibility value:
<Image Grid.Row="1" Visibility="Collapsed" Source="MyPicture.png">
<Image.Style>
<Style TargetType="Image">
<Style.Triggers>
<EventTrigger RoutedEvent="Loaded">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetProperty="Visibility"
Duration="0"
BeginTime="0:0:2">
<DiscreteObjectKeyFrame Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
<EventTrigger RoutedEvent="Unloaded">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetProperty="Visibility"
Duration="0"
BeginTime="0:0:0">
<DiscreteObjectKeyFrame Value="{x:Static Visibility.Collapsed}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
So the second animation will begin when the image is unloaded, has no duration and resets the Visibility value.

How to target a group of controls in a storyboard WPF

<Storyboard x:Key="OnClick1">
<DoubleAnimation Storyboard.TargetName="{StaticResource test}"
Storyboard.TargetProperty="Opacity"
From="1"
To="0"
RepeatBehavior="2000"
AutoReverse="True"
Duration="0:0:0.7"/>
</Storyboard>
<Window.Triggers>
<EventTrigger RoutedEvent="ButtonBase.Loaded" SourceName="button">
<BeginStoryboard Storyboard="{StaticResource OnClick1}"/>
</EventTrigger>
</Window.Triggers>
<Button x:Name="button2" x:key="test" Content="Button" Margin="234,140,164,0" Height="37" VerticalAlignment="Top"/>
<Button x:Name="button3" x:key="test" Content="Button" Margin="234,140,164,0" Height="37" VerticalAlignment="Top"/>
I am trying to add this double animation to multiple buttons without duplicating the double animation. Initially, I had the TargetName set to the name of the first button and it works but if added key to the button I get this message "The property "key" does not exist in WinFX namespace.
Give ButtonA the storyboard that drives its Opacity. For each other button,
<Button
x:Name="button3"
Opacity="{Binding Opacity, ElementName=button2}"
...
/>
Alternatively, put all the buttons inside a StackPanel (or Grid, or whatever), and animate the parent's Opacity.
The sample markup you have posted doesn't provide a reproducible sample of your issue but you could add a trigger to each Button that you want to animate:
<Window x:Class="WpfApplication1.Window1"
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"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<Storyboard x:Key="OnClick1">
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
From="1"
To="0"
RepeatBehavior="2000"
AutoReverse="True"
Duration="0:0:0.7"/>
</Storyboard>
</Window.Resources>
<StackPanel>
<Button x:Name="button2" Content="Button" Height="37" VerticalAlignment="Top">
<Button.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard Storyboard="{StaticResource OnClick1}"/>
</EventTrigger>
</Button.Triggers>
</Button>
<Button x:Name="button3" Content="Button" Height="37" VerticalAlignment="Top">
<Button.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard Storyboard="{StaticResource OnClick1}"/>
</EventTrigger>
</Button.Triggers>
</Button>
</StackPanel>
</Window>

How do I slide down a grid with animation on mouse hover in wpf?

My req is to have a grid of 2 rows - the first row will be filled with comboboxes as search criteria for a DB query. The second row will be a DataGrid with the results.
I want the upper grid to slide down from the top when I hover over it, and slide back up on mouse leave. I guess I can have a simple textblock at the top "Filters" and hovering over it will bring down the comboboxes?
I have something like this, but when mouse over, the animation goes up/down with out stopping.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.Triggers>
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="ControlsGrid"
Storyboard.TargetProperty="(Grid.Height)"
From="0"
To="66"
Duration="0:0:0.5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeave">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="ControlsGrid"
Storyboard.TargetProperty="(Grid.Height)"
From="66"
To="0"
Duration="0:0:0.5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Grid.Triggers>
<TextBlock HorizontalAlignment="Center" FontSize="20" Text="Filters..."/>
</Grid>
<Grid Margin="0" Name="ControlsGrid" VerticalAlignment="top" Background="Yellow"/>
<DataGrid Grid.Row="1" ColumnHeaderStyle="{DynamicResource GridViewColumnHeaderStyle}" Background="LightGray" RowBackground="LightYellow" AlternatingRowBackground="LightBlue"
x:Name="dataGridViewRoomQuery" BorderBrush="Gray" BorderThickness="5"/>
</Grid>
The problem with your approach is that the "hovering" Grid (the one with the event triggers) gets a MouseLeave event whenever the ControlsGrid is placed above it.
You have to put the ControlsGrid into the hovering Grid:
<Grid Grid.Row="0" Background="Transparent">
<Grid.Triggers>
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="ControlsGrid"
Storyboard.TargetProperty="Height"
To="66" Duration="0:0:0.5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeave">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="ControlsGrid"
Storyboard.TargetProperty="Height"
To="0" Duration="0:0:0.5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Grid.Triggers>
<TextBlock HorizontalAlignment="Center" FontSize="20" Text="Filters..."/>
<Grid Name="ControlsGrid" Height="0" VerticalAlignment="Top" Background="Yellow">
</Grid>
</Grid>
<DataGrid .../>

Animation during SelectionChanged

I have a TabControl where each TabItem has a separate control as its Content element. Now, I can easily execute a storyboard when switching to a tab by using a UserControl.Loaded EventTrigger. However, I also want to run an exit animation when switching from one tab to another (i.e. allow the old Content control to animate away, followed by the new Content control's entrance animation).
Is it possible to do this with standard WPF constructs?
If not, how would I go about developing a custom solution that handles this?
Edit:
I went ahead and made a modified TabControl that extends the base TabControl and overrode its OnSelectionChanged method as follows:
protected override void OnSelectionChanged(SelectionChangedEventArgs e)
{
if (e.AddedItems.Count == 1 && e.RemovedItems.Count == 1)
{
var oldTab = e.RemovedItems[0] as TabItem;
if (oldTab != null)
{
var exitStoryboard = /** code to find the storyboard **/
if (exitStoryboard != null)
{
exitStoryboard.Completed = (_, __) => base.OnSelectionChanged(e);
exitStoryboard.Begin();
return;
}
}
}
base.OnSelectionChanged(e);
}
This works, except when I click between the tabs too quickly in which case the base.OnSelectionChanged never gets called, presumably because the storyboard is not active any more. Tips?
Here's a solution for 2 tabs, the general idea is to pop up an image of the last tab after the selection changes, and then fade the current tab in.
With a little effort you could probably genericize it for any number of tabs by tracking the last tab for the VisualBrush in a property instead of the hardcoded "other" tab used here.
<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<TabControl>
<TabItem x:Name="tab1" Header="Tab 1">
<Border Background="Transparent">
<Grid>
<TextBlock FontSize="40" Foreground="Red" Text="Tab 1 Contents">
<TextBlock.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity">
<DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="0.0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimation
Duration="0:0:0.25"
From="1"
Storyboard.TargetName="tab2Shadow"
Storyboard.TargetProperty="Opacity"
To="0"/>
<DoubleAnimation
BeginTime="0:0:0.25"
Duration="0:0:0.25"
From="0"
Storyboard.TargetProperty="Opacity"
To="1"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</TextBlock.Triggers>
</TextBlock>
<Rectangle x:Name="tab2Shadow">
<Rectangle.Fill>
<VisualBrush
AlignmentX="Left"
AlignmentY="Top"
AutoLayoutContent="False"
Stretch="None"
Visual="{Binding ElementName=tab2, Path=Content}"/>
</Rectangle.Fill>
</Rectangle>
</Grid>
</Border>
</TabItem>
<TabItem x:Name="tab2" Header="Tab 2">
<Border Background="Transparent">
<Grid>
<TextBlock FontSize="40" Foreground="Red" Text="Tab 2 Contents">
<TextBlock.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity">
<DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="0.0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimation
Duration="0:0:0.25"
From="1"
Storyboard.TargetName="tab1Shadow"
Storyboard.TargetProperty="Opacity"
To="0"/>
<DoubleAnimation
BeginTime="0:0:0.25"
Duration="0:0:0.25"
From="0"
Storyboard.TargetProperty="Opacity"
To="1"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</TextBlock.Triggers>
</TextBlock>
<Rectangle x:Name="tab1Shadow">
<Rectangle.Fill>
<VisualBrush
AlignmentX="Left"
AlignmentY="Top"
AutoLayoutContent="False"
Stretch="None"
Visual="{Binding ElementName=tab1, Path=Content}"/>
</Rectangle.Fill>
</Rectangle>
</Grid>
</Border>
</TabItem>
</TabControl>
</Grid>
You can use the TabControl.SelectionChanged event.
You can define a custom style for your tabcontrol and do animation on Selector.SelectionChanged RoutedEvent
<Style x:Key="{x:Type TabControl}"
TargetType="TabControl">
<Setter Property="VerticalContentAlignment" Value="Stretch" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TabControl">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="40" />
<RowDefinition />
</Grid.RowDefinitions>
<UniformGrid Grid.Row="0"
Rows="1"
IsItemsHost="True" />
<ContentPresenter x:Name="TabContent"
Grid.Row="2"
Content="{TemplateBinding SelectedContent}">
</ContentPresenter>
</Grid>
<ControlTemplate.Triggers>
<EventTrigger RoutedEvent="Selector.SelectionChanged">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation From="0"
To="1"
Storyboard.TargetProperty="Opacity"
Storyboard.TargetName="TabContent"
Duration="0:0:0.5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Animation in visibility from hidden to collapsed and vice versa

I am trying to achieve something similar to iPhone message view. On a button click, a delete button would slide out for every message and on clicking "done" the delete buttons would slide in. I have been able to achieve that using mvvm except the sliding effect.
Here is the style I could write with my limited knowledge:
<Style TargetType="Border">
<Style.Triggers>
<DataTrigger Binding="{Binding ShowDeleteButton}" Value="false">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
Here "ShowDeleteButton" is a bool property in the view model. This works fine. but the collapsing and "getting visible" is happening abruptly and very fast. I need some sliding animation.
Please note that as the delete buttons disappear, the rest of the controls should take up the rest of space and, as the button appear, the existing controls should shrink and give space to the buttons.
I tried with storyboard animation but even after a couple hours I am not able to figure out the strange errors it is throwing. Here is the code:
<DataTrigger Binding="{Binding ShowDeleteButton}" Value="false">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard BeginTime="0:0:1">
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visiblity">
<DiscreteObjectKeyFrame Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard BeginTime="0:0:1">
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visiblity">
<DiscreteObjectKeyFrame Value="{x:Static Visibility.Visible}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
Can someone please help the soul in distress?
regards
Old question... huh...
Anyway... forget about visibility. The trick is to animate Width/Height of the Control placed in Grid's Column/Row where the Column/Row has Width set to Auto. Uff :)
So here is a Grid named "container" with two columns. In the first column can be placed whatever you want, but you should align it to Right since you want it to move when your delete button is displayed. And in the second column there is a Control (representing your DeleteButton) Notice that first column has Width="*" and second column has Width="Auto"
<Grid Background="Purple" Width="350" Height="100">
<CheckBox Content="Show" IsChecked="{Binding Path=ShowDeleteButton}" Height="16" HorizontalAlignment="Left" Margin="12,12,0,0" Name="checkBox1" VerticalAlignment="Top" />
<Grid x:Name="container" Margin="40,0,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid Name="content" Margin="0">
<Label Content="Look I'm flyin'!" Margin="0,30,10,0" VerticalAlignment="Top" HorizontalAlignment="Right"/>
</Grid>
<Control Grid.Column="1" Margin="0">
<Control.Template>
<ControlTemplate>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding ShowDeleteButton}" Value="true">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="flyout"
Storyboard.TargetProperty="(Grid.Width)"
From="0" To="120" Duration="0:0:1" AutoReverse="False"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="flyout"
Storyboard.TargetProperty="(Grid.Width)"
From="120" To="0" Duration="0:0:1" AutoReverse="False"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</ControlTemplate.Triggers>
<Grid x:Name="flyout" Width="0">
<Rectangle Fill="Green"/>
<Label Content="I'm DELETE button" Margin="10,30,0,0" VerticalAlignment="Top"/>
</Grid>
</ControlTemplate>
</Control.Template>
</Control>
</Grid>
</Grid>
And the Control in Grid's second column has DataTrigger based on your ViewModel's property "ShowDeleteButton"
Since the Width of column where the Control is placed is Auto you can change the width of the Control using simple DoubleAnimation and you get desired behavior.
EDIT
Look at this if you want the flyout to be over everything else.
<Grid x:Name="LayoutRoot">
<Grid x:Name="container" Width="120" HorizontalAlignment="Right">
<Button x:Name="button" Content="In" Margin="0,13,7.5,0" VerticalAlignment="Top" HorizontalAlignment="Right" d:LayoutOverrides="HorizontalAlignment">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="flyout"
Storyboard.TargetProperty="(Grid.Width)"
From="0" To="120" Duration="0:0:1" AutoReverse="False"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</Grid>
<Grid x:Name="flyout" Width="120" Margin="0" HorizontalAlignment="Right">
<Rectangle Fill="Green"/>
<Label Content="This is some label" Margin="6.038,27,1.006,0" VerticalAlignment="Top"/>
<Button Content="Out" Margin="11.917,58,0,0" VerticalAlignment="Top" HorizontalAlignment="Left" Width="80.083">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="flyout"
Storyboard.TargetProperty="(Grid.Width)"
From="120" To="0" Duration="0:0:1" AutoReverse="False"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</Grid>
</Grid>
Please note that button "Out" can be clicked while it's moving. It should be probably disabled. I just did it like this because I wanted to do it simple and all in xaml. Sure you can use mahapps. Or you can just make it as fast as it is in MahApps and it's impossible to click it twice. :) I have looked at MahApps FlyOutDemo and my solution looks much simpler to me. And I don't need third party library.

Resources