Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 534
sohum Avatar asked Nov 14 '22 00:11

sohum


1 Answers

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>
like image 163
Robert Macnee Avatar answered Dec 07 '22 22:12

Robert Macnee