具有支持全方位动画的扩展器 [英] Expander with animation that support all direction

查看:77
本文介绍了具有支持全方位动画的扩展器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的目标:要在展开时使用动画创建自定义展开器,并且应该支持所有方向.

My Objective: is to create a Custom Expander with Animation on expanding and should support for all the directions.

我尝试过的事情:我已经在.我对其进行了修改,并根据需要使其工作.我的解决方案可以与Up一起使用,即使在Down Direction上也可以使它工作.

What I tried: I have Implemented a solution with the help of this. I modified it and made it work based on my need. My solution will work with Up and I can able to make it work even with Down Direction.

我现在的问题是什么:我无法使其适用于所有方向.我尝试并无法使其在将ExpanderDirection设置为LeftRight时起作用.

Whats my problem now: I couldn't make it work with all Directions. I tried and failed to make it work on setting ExpanderDirection to Left and Right.

扩展器模板:

   <ControlTemplate x:Key="AnimatedExpanderButtonTemp" TargetType="{x:Type ToggleButton}">
        <Border x:Name="ExpanderButtonBorder"
                Background="{TemplateBinding Background}"
                BorderBrush="{TemplateBinding BorderBrush}"
                BorderThickness="{TemplateBinding BorderThickness}"
                Padding="{TemplateBinding Padding}"
                >
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <Rectangle Fill="Transparent"
                           Grid.ColumnSpan="2"/>
                <Ellipse Name="Circle"
                     Grid.Column="0"
                     Stroke="DarkGray"
                     Width="20"
                     Height="20"
                     HorizontalAlignment="Center"
                     VerticalAlignment="Center"
                     />
                <Path x:Name="Arrow"
                  Grid.Column="0"
                  Data="M 1,1.5 L 4.5,5 8,1.5"
                  Stroke="#FF666666"
                  StrokeThickness="2"
                  HorizontalAlignment="Center"
                  VerticalAlignment="Center"
                  RenderTransformOrigin="0.5,0.5"
                  >
                    <Path.RenderTransform>
                        <RotateTransform Angle="0"/>
                    </Path.RenderTransform>
                </Path>
                <ContentPresenter x:Name="HeaderContent"
                                  Grid.Column="1"
                                  Margin="4,0,0,0"
                                  ContentSource="Content"/>
            </Grid>
        </Border>
        <ControlTemplate.Triggers>
            <!-- Animate arrow when toggled-->
            <Trigger Property="IsChecked"
                     Value="True">
                <Trigger.EnterActions>
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation Storyboard.TargetName="Arrow"
                                             Storyboard.TargetProperty="(Path.RenderTransform).(RotateTransform.Angle)"
                                             To="180"
                                             Duration="0:0:0.4"/>
                        </Storyboard>
                    </BeginStoryboard>
                </Trigger.EnterActions>
                <Trigger.ExitActions>
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation Storyboard.TargetName="Arrow"
                                             Storyboard.TargetProperty="(Path.RenderTransform).(RotateTransform.Angle)"
                                             To="0"
                                             Duration="0:0:0.4"/>
                        </Storyboard>
                    </BeginStoryboard>
                </Trigger.ExitActions>
            </Trigger>

            <!-- MouseOver, Pressed behaviours-->
            <Trigger Property="IsMouseOver"
                             Value="true">
                <Setter Property="Stroke"
                                Value="#FF3C7FB1"
                                TargetName="Circle"/>
                <Setter Property="Stroke"
                                Value="#222"
                                TargetName="Arrow"/>
            </Trigger>
            <Trigger Property="IsPressed"
                             Value="true">
                <Setter Property="Stroke"
                                Value="#FF526C7B"
                                TargetName="Circle"/>
                <Setter Property="StrokeThickness"
                                Value="1.5"
                                TargetName="Circle"/>
                <Setter Property="Stroke"
                                Value="#FF003366"
                                TargetName="Arrow"/>
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>


    <!-- Slide Out Content Expander's Template, 
    Uses: AnimatedExpanderButtonTemp from above, 
          MultiplyConverter in codebehind-->
    <local:MultiplyConverter x:Key="multiplyConverter" />
    <ControlTemplate x:Key="RevealExpanderTemp" TargetType="{x:Type Expander}">
        <DockPanel>
            <Border Background="{Binding Path=Background, RelativeSource={RelativeSource TemplatedParent}}" HorizontalAlignment="Stretch" DockPanel.Dock="Bottom" Padding="5,3">
                <ToggleButton x:Name="ExpanderButton" HorizontalAlignment="Center" HorizontalContentAlignment="Center"                         
                          Template="{StaticResource AnimatedExpanderButtonTemp}"
                          Content="{TemplateBinding Header}"
                          IsChecked="{Binding Path=IsExpanded, RelativeSource={RelativeSource TemplatedParent}}"
                          OverridesDefaultStyle="True"
                          Padding="1.5,0">
                </ToggleButton>
            </Border>
            <ScrollViewer x:Name="ExpanderContentScrollView" DockPanel.Dock="Top"
                          HorizontalScrollBarVisibility="Hidden"
                          VerticalScrollBarVisibility="Hidden"
                          HorizontalContentAlignment="Stretch"
                          VerticalContentAlignment="Bottom"
                          >
                <ScrollViewer.Tag>
                    <sys:Double>0.0</sys:Double>
                </ScrollViewer.Tag>
                <ScrollViewer.Height>
                    <MultiBinding Converter="{StaticResource multiplyConverter}">
                        <Binding Path="ActualHeight" ElementName="ExpanderContent"/>
                        <Binding Path="Tag" RelativeSource="{RelativeSource Self}" />
                    </MultiBinding>
                </ScrollViewer.Height>
                <ContentPresenter x:Name="ExpanderContent" ContentSource="Content"/>
            </ScrollViewer>
        </DockPanel>
        <ControlTemplate.Triggers>
            <Trigger Property="IsExpanded" Value="True">
                <Trigger.EnterActions>
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation Storyboard.TargetName="ExpanderContentScrollView"
                                             Storyboard.TargetProperty="Tag"                                                 
                                             To="1"
                                             Duration="0:0:0.4"/>
                        </Storyboard>
                    </BeginStoryboard>
                </Trigger.EnterActions>
                <Trigger.ExitActions>
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation Storyboard.TargetName="ExpanderContentScrollView"
                                             Storyboard.TargetProperty="Tag"                                                 
                                             To="0"
                                             Duration="0:0:0.4"/>
                        </Storyboard>
                    </BeginStoryboard>
                </Trigger.ExitActions>
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>

MultiplyConverter.cs(模板所需)

public class MultiplyConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        double result = 1.0;
        for (int i = 0; i < values.Length; i++)
        {
            if (values[i] is double)
                result *= (double)values[i];
        }

        return result;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new Exception("Not implemented");
    }
}

像这样使用它:

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

    <Grid Grid.Row="0" Background="Orange">

     <Expander Template="{StaticResource RevealExpanderTemp}" 
              OverridesDefaultStyle="True"
              HorizontalAlignment="Left"
              VerticalAlignment="Top" Background="LightGray">
        <StackPanel>
            <TextBlock Text="This is Sample Text for Expander" Margin="5"/>
            <TextBlock Text="This is Sample Text for Expander" Margin="5"/>
            <TextBlock Text="This is Sample Text for Expander" Margin="5"/>
            <TextBlock Text="This is Sample Text for Expander" Margin="5"/>
            <TextBlock Text="This is Sample Text for Expander" Margin="5"/>
            <TextBlock Text="This is Sample Text for Expander" Margin="5"/>
            <TextBlock Text="This is Sample Text for Expander" Margin="5"/>
            <TextBlock Text="This is Sample Text for Expander" Margin="5"/>
            <TextBlock Text="This is Sample Text for Expander" Margin="5"/>
            <TextBlock Text="This is Sample Text for Expander" Margin="5"/>                
        </StackPanel>
    </Expander>
    </Grid>
    <Grid Grid.Row="2" Background="Chocolate" />

</Grid>

上述解决方案不适用于ExpandDirection="Left" or "Right"

Above solution will not work with ExpandDirection="Left" or "Right"

关于如何使它与所有方向或其他替代方法配合使用的任何建议?

Any suggestions on how could I make it work with all Directions or any other alternatives for this?

推荐答案

经过8个小时的努力,我找到了解决问题的方法.让我回答我自己的问题,以便为其他人寻找解决方案节省时间.

After 8 hours of struggle, I found the workaround for my question. Let me answer my own question so that It may save some time for other peoples looking for solution.

扩展器的控制模板:

    <ControlTemplate x:Key="AnimatedExpanderButtonTemp" TargetType="{x:Type ToggleButton}">
        <Border x:Name="ExpanderArrow" CornerRadius="5"
                Background="{TemplateBinding Background}"
                BorderBrush="{TemplateBinding BorderBrush}"
                BorderThickness="{TemplateBinding BorderThickness}"
                Padding="{TemplateBinding Padding}"
                >
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"/>                        
                </Grid.ColumnDefinitions>
                <Rectangle Fill="Transparent"
                           Grid.ColumnSpan="2"/>
                <Ellipse Name="Circle"
                     Grid.Column="0"
                     Stroke="DarkGray"
                     Width="20"
                     Height="20"
                     HorizontalAlignment="Center"
                     VerticalAlignment="Center"
                     />
                <Path x:Name="Arrow"
                  Grid.Column="0"
                  Data="M 0 0 L 3,6 L 6,0"
                  Stroke="#FF666666"
                  StrokeThickness="2"
                  HorizontalAlignment="Center"
                  VerticalAlignment="Center"
                  RenderTransformOrigin="0.5,0.5"
                  >
                    <Path.RenderTransform>
                        <RotateTransform Angle="0"/>
                    </Path.RenderTransform>
                </Path>
                <ContentPresenter x:Name="HeaderContent"                                      
                                  Margin="4,0,0,0"
                                  ContentSource="Content"/>
            </Grid>
        </Border>
        <ControlTemplate.Triggers>
            <Trigger Property="DockPanel.Dock"
                     Value="Right">
                <Setter Property="Data" TargetName="Arrow" Value="M 0 0 L 3 3 L 0 6 "/>

            </Trigger>

            <Trigger Property="DockPanel.Dock"
                     Value="Left">
                <Setter Property="Data" TargetName="Arrow" Value="M 0 0 L 3 3 L 0 6"/>

            </Trigger>

            <Trigger Property="DockPanel.Dock"
                     Value="Top">
                <Setter Property="Data" TargetName="Arrow" Value="M 0 0 L 3,6 L 6,0"/>

            </Trigger>



            <!-- Animate arrow when toggled-->
            <Trigger Property="IsChecked"
                     Value="True">
                <Trigger.EnterActions>
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation Storyboard.TargetName="Arrow"
                                             Storyboard.TargetProperty="(Path.RenderTransform).(RotateTransform.Angle)"
                                             To="180"
                                             Duration="0:0:0.4"/>
                        </Storyboard>
                    </BeginStoryboard>
                </Trigger.EnterActions>
                <Trigger.ExitActions>
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation Storyboard.TargetName="Arrow"
                                             Storyboard.TargetProperty="(Path.RenderTransform).(RotateTransform.Angle)"
                                             To="0"
                                             Duration="0:0:0.4"/>
                        </Storyboard>
                    </BeginStoryboard>
                </Trigger.ExitActions>
            </Trigger>

            <!-- MouseOver, Pressed behaviours-->
            <Trigger Property="IsMouseOver"
                             Value="true">
                <Setter Property="Stroke"
                                Value="#FF3C7FB1"
                                TargetName="Circle"/>
                <Setter Property="Stroke"
                                Value="#222"
                                TargetName="Arrow"/>
            </Trigger>
            <Trigger Property="IsPressed"
                             Value="true">
                <Setter Property="Stroke"
                                Value="#FF526C7B"
                                TargetName="Circle"/>
                <Setter Property="StrokeThickness"
                                Value="1.5"
                                TargetName="Circle"/>
                <Setter Property="Stroke"
                                Value="#FF003366"
                                TargetName="Arrow"/>
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>


    <!-- Slide Out Content Expander's Template, 
    Uses: AnimatedExpanderButtonTemp from above, 
          MultiplyConverter in codebehind-->
    <local:MultiplyConverter x:Key="multiplyConverter" />
    <ControlTemplate x:Key="RevealExpanderTemp" TargetType="{x:Type Expander}">
        <DockPanel>
            <!--<Border x:Name="ExpanderButtonBorder" Background="{Binding Path=Background, RelativeSource={RelativeSource TemplatedParent}}" HorizontalAlignment="Stretch" DockPanel.Dock="Bottom" Padding="5,3">-->
            <ToggleButton x:Name="ExpanderButton" HorizontalAlignment="Stretch" DockPanel.Dock="Bottom"
                          Template="{StaticResource AnimatedExpanderButtonTemp}"
                          Content="{TemplateBinding Header}"
                          IsChecked="{Binding Path=IsExpanded, RelativeSource={RelativeSource TemplatedParent}}"
                          Background="{Binding Path=Background, RelativeSource={RelativeSource TemplatedParent}}"
                          OverridesDefaultStyle="True"
                          Padding="0">
                </ToggleButton>
            <!--</Border>-->
            <ScrollViewer x:Name="ExpanderContentScrollView" DockPanel.Dock="Top"
                          HorizontalScrollBarVisibility="Hidden"
                          VerticalScrollBarVisibility="Hidden"
                          HorizontalContentAlignment="Stretch"
                          VerticalContentAlignment="Bottom"
                          >
                <ScrollViewer.Tag>
                    <sys:Double>0.0</sys:Double>
                </ScrollViewer.Tag>                    
                <ContentPresenter x:Name="ExpanderContent" ContentSource="Content"/>
            </ScrollViewer>
        </DockPanel>
        <ControlTemplate.Triggers>

            <Trigger Property="ExpandDirection" Value="Right">
                <Setter Property="DockPanel.Dock" TargetName="ExpanderButton" Value="Right"/>
                <Setter Property="DockPanel.Dock" TargetName="ExpanderContentScrollView" Value="Left"/>
                <Setter Property="Width" TargetName="ExpanderContentScrollView">
                    <Setter.Value>
                        <MultiBinding Converter="{StaticResource multiplyConverter}">
                            <Binding Path="ActualWidth" ElementName="ExpanderContent"/>
                            <Binding Path="Tag" RelativeSource="{RelativeSource Self}" />
                        </MultiBinding>
                    </Setter.Value>
                </Setter>                    
            </Trigger>
            <Trigger Property="ExpandDirection" Value="Up">
                <Setter Property="DockPanel.Dock" TargetName="ExpanderButton" Value="Top"/>
                <Setter Property="DockPanel.Dock" TargetName="ExpanderContentScrollView" Value="Bottom"/>
                <Setter Property="Height" TargetName="ExpanderContentScrollView">
                    <Setter.Value>
                        <MultiBinding Converter="{StaticResource multiplyConverter}">
                            <Binding Path="ActualHeight" ElementName="ExpanderContent"/>
                            <Binding Path="Tag" RelativeSource="{RelativeSource Self}" />
                        </MultiBinding>
                    </Setter.Value>
                </Setter>
            </Trigger>
            <Trigger Property="ExpandDirection" Value="Left">
                <Setter Property="DockPanel.Dock" TargetName="ExpanderButton" Value="Left"/>
                <Setter Property="DockPanel.Dock" TargetName="ExpanderContentScrollView" Value="Right"/>
                <Setter Property="Width" TargetName="ExpanderContentScrollView">
                    <Setter.Value>
                        <MultiBinding Converter="{StaticResource multiplyConverter}">
                            <Binding Path="ActualWidth" ElementName="ExpanderContent"/>
                            <Binding Path="Tag" RelativeSource="{RelativeSource Self}" />
                        </MultiBinding>
                    </Setter.Value>
                </Setter>
            </Trigger>

            <Trigger Property="ExpandDirection" Value="Down">                    
                <Setter Property="Height" TargetName="ExpanderContentScrollView">
                    <Setter.Value>
                        <MultiBinding Converter="{StaticResource multiplyConverter}">
                            <Binding Path="ActualHeight" ElementName="ExpanderContent"/>
                            <Binding Path="Tag" RelativeSource="{RelativeSource Self}" />
                        </MultiBinding>
                    </Setter.Value>
                </Setter>
            </Trigger>
            <Trigger Property="IsEnabled" Value="false">
                <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
            </Trigger>


            <Trigger Property="IsExpanded" Value="True">
                <Trigger.EnterActions>
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation Storyboard.TargetName="ExpanderContentScrollView"
                                             Storyboard.TargetProperty="Tag"                                                 
                                             To="1"
                                             Duration="0:0:0.4"/>
                        </Storyboard>
                    </BeginStoryboard>
                </Trigger.EnterActions>
                <Trigger.ExitActions>
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation Storyboard.TargetName="ExpanderContentScrollView"
                                             Storyboard.TargetProperty="Tag"                                                 
                                             To="0"
                                             Duration="0:0:0.4"/>
                        </Storyboard>
                    </BeginStoryboard>
                </Trigger.ExitActions>
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>

MultiplyConverter.cs(模板所需)

public class MultiplyConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        double result = 1.0;
        for (int i = 0; i < values.Length; i++)
        {
            if (values[i] is double)
                result *= (double)values[i];
        }

        return result;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new Exception("Not implemented");
    }
}

演示:

<!-- Small demo of Expander Template above-->
<Grid >
    <Grid.RowDefinitions>
        <RowDefinition Height="auto" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>

    <Grid Grid.Row="0" Background="Orange">

    <Expander Template="{StaticResource RevealExpanderTemp}"  ExpandDirection="Right"
              OverridesDefaultStyle="True"
              HorizontalAlignment="Left"
              VerticalAlignment="Top" Background="LightGray">
        <StackPanel>
            <TextBlock Text="This is Sample Text for Expander" Margin="5"/>
            <TextBlock Text="This is Sample Text for Expander" Margin="5"/>
            <TextBlock Text="This is Sample Text for Expander" Margin="5"/>
            <TextBlock Text="This is Sample Text for Expander" Margin="5"/>
            <TextBlock Text="This is Sample Text for Expander" Margin="5"/>
            <TextBlock Text="This is Sample Text for Expander" Margin="5"/>
            <TextBlock Text="This is Sample Text for Expander" Margin="5"/>
            <TextBlock Text="This is Sample Text for Expander" Margin="5"/>
            <TextBlock Text="This is Sample Text for Expander" Margin="5"/>
            <TextBlock Text="This is Sample Text for Expander" Margin="5"/>                
        </StackPanel>
    </Expander>
    </Grid>
    <Grid Grid.Row="2" Background="Chocolate" />

</Grid>

该代码未经过完整测试,并且可能存在错误.

The code was not tested fully and there may be bugs.

这篇关于具有支持全方位动画的扩展器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆