Home > Enterprise >  How to achieve correct underline animation when selecting between TabItems?
How to achieve correct underline animation when selecting between TabItems?

Time:03-29

I have a total of four tab items and the underlined rectangles have different widths depending on which of the four tab items is selected. But my data trigger binding doesn't work.

Expected:

Suppose I select the second tab item, and after I select the fourth tab item, the underline rectangle should move from the second tab item to the fourth tab item with the correct entry and exit animation as well as the correct width.

I have the following code but I don't know how to do it.

<Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="50"/>
        </Grid.RowDefinitions>

        <TabControl Grid.Row="0"     x:Name="TestTabs">
            <TabItem Header="News"/>
            <TabItem Header="Files"/>
            <TabItem Header="Settings"/>
            <TabItem Header="Help"/>

        </TabControl>
        <DockPanel x:Name="rp" Grid.Row="0" LastChildFill="False" HorizontalAlignment="Stretch">
            <Canvas DockPanel.Dock="Left">
                <Rectangle x:Name="MySeparator3" Fill="Orange"  VerticalAlignment="Top" Width="40" Height="4" Margin="3,25,0,0"   SnapsToDevicePixels="True" UseLayoutRounding="True" RenderOptions.EdgeMode="Aliased" RenderOptions.BitmapScalingMode="HighQuality" >
                    <Rectangle.Style>
                        <Style TargetType="{x:Type Rectangle}">
                            <Setter Property="SnapsToDevicePixels" Value="True"/>
                            <Setter Property="RenderOptions.EdgeMode" Value="Aliased"/>
                            <Setter Property="Visibility" Value="Visible"/>
                            <Setter Property="IsEnabled" Value="True"/>
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding ElementName=TestTabs, Path=SelectedIndex}" Value="1">
                                    <Setter Property="SnapsToDevicePixels" Value="True"/>
                                    <Setter Property="RenderOptions.EdgeMode" Value="Aliased"/>
                                    <Setter Property="Visibility" Value="Visible" />
                                    <Setter Property="IsEnabled" Value="True" />
                                    <DataTrigger.EnterActions>
                                        <BeginStoryboard Name="MyBeginStoryboard11">
                                            <Storyboard>
                                                <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" From="0" To="40" Duration="0:0:0.2"></DoubleAnimation>
                                                <DoubleAnimation Storyboard.TargetProperty="Width"   From="40" To="35" Duration="0:0:0.2"></DoubleAnimation>
                                            </Storyboard>
                                        </BeginStoryboard>
                                    </DataTrigger.EnterActions>
                                    <DataTrigger.ExitActions>
                                        <BeginStoryboard Name="MyBeginStoryboard1">
                                            <Storyboard>
                                                <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" From="40" To="0" Duration="0:0:0.2"></DoubleAnimation>
                                                <DoubleAnimation Storyboard.TargetProperty="Width"   From="35" To="40" Duration="0:0:0.2"></DoubleAnimation>
                                            </Storyboard>
                                        </BeginStoryboard>
                                    </DataTrigger.ExitActions>
                                </DataTrigger>
                                <MultiDataTrigger>
                                    <MultiDataTrigger.Conditions>
                                        <Condition  Binding="{Binding ElementName=TestTabs, Path=SelectedIndex}" Value="2"/>
                                    </MultiDataTrigger.Conditions>
                                    <MultiDataTrigger.EnterActions>
                                        <BeginStoryboard Name="MyBeginStoryboard19">
                                            <Storyboard>
                                                <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" From="0" To="73" Duration="0:0:0.2"></DoubleAnimation>
                                                <DoubleAnimation Storyboard.TargetProperty="Width"   From="40" To="50" Duration="0:0:0.2"></DoubleAnimation>
                                            </Storyboard>
                                        </BeginStoryboard>
                                    </MultiDataTrigger.EnterActions>
                                    <MultiDataTrigger.ExitActions>
                                        <BeginStoryboard Name="MyBeginStoryboard5">
                                            <Storyboard>
                                                <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" From="73" To="0" Duration="0:0:0.2"></DoubleAnimation>
                                                <DoubleAnimation Storyboard.TargetProperty="Width"   From="50" To="40" Duration="0:0:0.2"></DoubleAnimation>
                                            </Storyboard>
                                        </BeginStoryboard>
                                    </MultiDataTrigger.ExitActions>
                                </MultiDataTrigger>
                            </Style.Triggers>
                        </Style>
                    </Rectangle.Style>
                </Rectangle>
            </Canvas>
        </DockPanel>
    </Grid>

Actual result:

enter image description here

CodePudding user response:

MainWindow.xaml:

 <Grid>
     <Grid.RowDefinitions>
         <RowDefinition Height="*"/>
         <RowDefinition Height="50"/>
     </Grid.RowDefinitions>
     <TabControl Grid.Row="0"   x:Name="TestTabs" Loaded="TestTabs_Loaded"  SelectionChanged="TestTabs_SelectionChanged">
         <TabItem Name="Tab1" Header="News"/>
         <TabItem Name="Tab2" Header="Files"/>
         <TabItem Name="Tab3" Header="Settings"/>
         <TabItem Name="Tab4" Header="Help"/>
     </TabControl>
     <DockPanel x:Name="rp" Grid.Row="0" LastChildFill="False" HorizontalAlignment="Stretch">
         <Canvas DockPanel.Dock="Left">
             <Rectangle x:Name="MySeparator3" Fill="Orange"  VerticalAlignment="Top"  Height="4" Margin="3,25,0,0"   Visibility="Visible"  IsEnabled="True"
                        SnapsToDevicePixels="True" UseLayoutRounding="True" RenderOptions.EdgeMode="Aliased" RenderOptions.BitmapScalingMode="HighQuality" >
             </Rectangle>
         </Canvas>
     </DockPanel>
     <TextBlock Grid.Row="1" Text="{Binding ElementName=Tab1,Path=ActualWidth}" Height="50" Width="100"/>
 </Grid>

MainWindow.xaml.cs:

    using System;
 using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Media;
 using System.Windows.Media.Animation;
    
 namespace RectangleWidthAndSlide
 {
   public partial class MainWindow : Window
   {
     public MainWindow()
     {
       InitializeComponent();
     }
     public int Start{ get;set;}
     private void TestTabs_SelectionChanged(object sender, SelectionChangedEventArgs e)
     {
         TabItem ti = ((sender as TabControl).SelectedItem as TabItem);
       double sz1 = ti.ActualWidth;
       MySeparator3.Width = sz1;
       MySeparator3.UpdateLayout();
       if (e.RemovedItems.Count > 0)
       {
         var oldTabItem = e.RemovedItems[0] as TabItem;
         DoubleAnimation translate_x = null;
         if (oldTabItem.Name == "Tab1")
         {
           switch (ti.Name)
           {
             case "Tab2":
               translate_x = new DoubleAnimation()
               {
                 From = 0,
                 To = 40,
                 Duration = TimeSpan.FromSeconds(0.2),
               };
               break;
             case "Tab3":
               translate_x = new DoubleAnimation()
               {
                 From = 0,
                 To = 75,
                 Duration = TimeSpan.FromSeconds(0.2),
               };
               break;
             case "Tab4":
               translate_x = new DoubleAnimation()
               {
                 From = 0,
                 To = 130,
                 Duration = TimeSpan.FromSeconds(0.2),
               };
               break;
           }
           var translate_y = new DoubleAnimation()
           {
             From = 0,
             To = 0,
             Duration = TimeSpan.FromSeconds(1),
           };
           TranslateTransform translateTransform1 = new TranslateTransform();
           translateTransform1.BeginAnimation(TranslateTransform.XProperty, translate_x);
           translateTransform1.BeginAnimation(TranslateTransform.YProperty, translate_y);
           MySeparator3.RenderTransform = translateTransform1;
         }
         if (oldTabItem.Name == "Tab2")
         {
           switch (ti.Name)
           {
             case "Tab1":
               translate_x = new DoubleAnimation()
               {
                 From = 40,
                 To = 0,
                 Duration = TimeSpan.FromSeconds(0.2),
               };
               break;
             case "Tab3":
               translate_x = new DoubleAnimation()
               {
                 From = 40,
                 To = 75,
                 Duration = TimeSpan.FromSeconds(0.2),
               };
               break;
             case "Tab4":
               translate_x = new DoubleAnimation()
               {
                 From = 40,
                 To = 130,
                 Duration = TimeSpan.FromSeconds(0.2),
               };
               break;
           }
           var translate_y = new DoubleAnimation()
           {
             From = 0,
             To = 0,
             Duration = TimeSpan.FromSeconds(1),
           };
           TranslateTransform translateTransform1 = new TranslateTransform();
           translateTransform1.BeginAnimation(TranslateTransform.XProperty, translate_x);
           translateTransform1.BeginAnimation(TranslateTransform.YProperty, translate_y);
           MySeparator3.RenderTransform = translateTransform1;
         }
         if (oldTabItem.Name == "Tab3")
         {
           switch (ti.Name)
           {
             case "Tab1":
               translate_x = new DoubleAnimation()
               {
                 From = 75,
                 To = 0,
                 Duration = TimeSpan.FromSeconds(0.2),
               };
               break;
             case "Tab2":
               translate_x = new DoubleAnimation()
               {
                 From = 75,
                 To = 40,
                 Duration = TimeSpan.FromSeconds(0.2),
               };
               break;
             case "Tab4":
               translate_x = new DoubleAnimation()
               {
                 From = 75,
                 To = 130,
                 Duration = TimeSpan.FromSeconds(0.2),
               };
               break;
           }
           var translate_y = new DoubleAnimation()
           {
             From = 0,
             To = 0,
             Duration = TimeSpan.FromSeconds(1),
           };
           TranslateTransform translateTransform1 = new TranslateTransform();
           translateTransform1.BeginAnimation(TranslateTransform.XProperty, translate_x);
           translateTransform1.BeginAnimation(TranslateTransform.YProperty, translate_y);
           MySeparator3.RenderTransform = translateTransform1;
         }
         if(oldTabItem.Name == "Tab4")
         {
           switch (ti.Name)
           {
             case "Tab1":
               translate_x = new DoubleAnimation()
               {
                 From = 130,
                 To = 0,
                 Duration = TimeSpan.FromSeconds(0.2),
               };
               break;
             case "Tab2":
               translate_x = new DoubleAnimation()
               {
                 From = 130,
                 To = 40,
                 Duration = TimeSpan.FromSeconds(0.2),
               };
               break;
             case "Tab3":
               translate_x = new DoubleAnimation()
               {
                 From = 130,
                 To = 75,
                 Duration = TimeSpan.FromSeconds(0.2),
               };
               break;
           }
           var translate_y = new DoubleAnimation()
           {
             From = 0,
             To = 0,
             Duration = TimeSpan.FromSeconds(1),
           };
           TranslateTransform translateTransform1 = new TranslateTransform();
           translateTransform1.BeginAnimation(TranslateTransform.XProperty, translate_x);
           translateTransform1.BeginAnimation(TranslateTransform.YProperty, translate_y);
           MySeparator3.RenderTransform = translateTransform1;
         }
       }
     }
     private void TestTabs_Loaded(object sender, RoutedEventArgs e)
     {
       var tabControl = (TabControl)sender;
       tabControl.SelectedItem = Tab1;
       TabItem ti = (tabControl.SelectedItem as TabItem);
       double sz1 = ti.ActualWidth-5;
       MySeparator3.Width = sz1;
       MySeparator3.UpdateLayout();
     }
   }
 }

The result: enter image description here

  • Related