ScaleTransform.ScaleY UIElement,不保留空间

时间:2015-06-08 11:03:06

标签: xaml windows-runtime winrt-xaml

我有一个ListView,其ItemTemplate是一个自定义控件(充当扩展器),它具有一个始终可见的切换和下面的边框内容,可根据需要进行扩展。

<ControlTemplate TargetType="local:ExpanderControl">
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="*" />
                        </Grid.RowDefinitions>
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="ExpandStateGroup">
                                <VisualState x:Name="Collapsed">
                                    <!--<Storyboard>
                                        <DoubleAnimation Storyboard.TargetName="PART_ExpandableContent" 
                                                         Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)"
                                                         To="0.0"
                                                         Duration="0:0:0.2"
                                                         AutoReverse="False"
                                                         EnableDependentAnimation="True"></DoubleAnimation>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Expanded">
                                    <Storyboard>
                                        <DoubleAnimation Storyboard.TargetName="PART_ExpandableContent" 
                                                         Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)"
                                                         To="1.0"
                                                         Duration="0:0:0.2"
                                                         AutoReverse="False"
                                                         EnableDependentAnimation="True"></DoubleAnimation>
                                    </Storyboard>-->
                                    <Storyboard>
                                        <DoubleAnimation Storyboard.TargetName="PART_ExpandableContent" 
                                                         Storyboard.TargetProperty="Height"
                                                         To="0.0"
                                                         Duration="0:0:0.2"
                                                         AutoReverse="False"
                                                         EnableDependentAnimation="True"></DoubleAnimation>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Expanded">
                                    <Storyboard>
                                        <DoubleAnimation Storyboard.TargetName="PART_ExpandableContent" 
                                                         Storyboard.TargetProperty="Height"
                                                         To="100.0"
                                                         Duration="0:0:0.2"
                                                         AutoReverse="False"
                                                         EnableDependentAnimation="True"></DoubleAnimation>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                        <ToggleButton x:Name="PART_expanderButton" Foreground="{TemplateBinding Foreground}"
                                      Style="{StaticResource ExpanderButtonStyle}" Background="{TemplateBinding Background}"
                                      BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"
                                      IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsExpanded , Mode=TwoWay}">
                            <ContentPresenter VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                              HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                              ContentTemplate="{TemplateBinding HeaderContentTemplate}" Content="{TemplateBinding Header}"
                                              Foreground="{TemplateBinding Foreground}" FontSize="{TemplateBinding FontSize}"
                                              FontWeight="{TemplateBinding FontWeight}" FontStyle="{TemplateBinding FontStyle}"
                                              Margin="{TemplateBinding Padding}"/>
                        </ToggleButton>
                        <Border Grid.Row="1" x:Name="PART_ExpandableContent" Background="{TemplateBinding Background}"
                                BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"
                                Height="0">
                            <!--<Border.RenderTransform>
                                <ScaleTransform ScaleY="0.0" />
                            </Border.RenderTransform>-->
                            <ContentPresenter x:Name="PART_ExpandableContentPresenter" Content="{TemplateBinding Content}"
                                    ContentTemplate="{TemplateBinding ContentTemplate}">
                            </ContentPresenter>
                        </Border>
                    </Grid>
                </ControlTemplate>

我一直在玩VisualState尝试实现一个简单的动画:点击时,项目会展开,再次点击时会折叠。

在“可扩展”控件上使用可见性是一个选项,除了我想要一个“增长”动画,让高度增加直到它的全高,而不是可见性提供的捕捉效果。

我也搞乱了ScaleY效果,它几乎是我想要的,除了父级保留可扩展控件的高度,即使这是ScaleY = 0,在列表上的每个元素之间留下一个很大的不需要的空间有道理。

现在,上面演示的工作解决方案是在控件上设置了一个高度值,并在此值和0之间变化。但我希望在不必硬编码高度的情况下实现更可重用的解决方案。

任何帮助将不胜感激。 谢谢!

1 个答案:

答案 0 :(得分:0)

我最近构建了一个自定义控件,它可以执行与您之后的行为类似的操作。这是一个测试版本,以显示我的意思,因为您可能适应您的项目。

两个关键点是控制您要移动的项目位于StackPanel并且操纵高度属性而不是使用Transform.ScaleY

MainPage.xaml中

<Grid Background="Black">
    <StackPanel Orientation="Vertical" Margin="20"
                VerticalAlignment="Top">
        <Button x:Name="ExpandButton" Width="200" Height="75" Content="expand"
                Foreground="White" BorderBrush="White"
                Click="ExpandButton_Click" />

        <Rectangle x:Name="Red" Width="200" Height="200" Fill="Red" />
        <Rectangle x:Name="Green" Width="200" Height="200" Fill="Green" />
        <Rectangle x:Name="Blue" Width="200" Height="200" Fill="Blue" />
    </StackPanel>
</Grid>

MainPage.xaml.cs

public sealed partial class MainPage : Page
{
    private double panelHeight = 0.0;
    private bool contentOpen = false;

    public MainPage()
    {
        this.InitializeComponent();

        //this is the Green rectangles height we want to expand on Button Click
        panelHeight = this.Green.ActualHeight;

        //expandable item should be 0 height is Flag is false
        if (!contentOpen)
            Green.Height = 0.0;
    }

    private void ExpandButton_Click(object sender, RoutedEventArgs e)
    {            
        OpenCloseAnimation animate;

        //Create animation based on Flag.
        if (contentOpen)
        {
            //pass in zero height as we are closing
            animate = new OpenCloseAnimation(Green, 0);
            contentOpen = false;
            this.ExpandButton.Content = "expand";
        }
        else
        {
            //pass in Green rectangles actual height as we are opening
            animate = new OpenCloseAnimation(Green, panelHeight);
            contentOpen = true;
            this.ExpandButton.Content = "close";
        }

        //start the animation
        animate.sb.Begin();          
    }
}

OpenCloseAnimation.cs

public class OpenCloseAnimation
{
    public Storyboard sb { get; set; }
    private double _height;
    private FrameworkElement _element;

    public OpenCloseAnimation(FrameworkElement element, double height)
    {
        _element = element;
        _height = height;
        CreateStoryboard();
    }

    public void CreateStoryboard()
    {
        sb = new Storyboard();

        var animation = new DoubleAnimationUsingKeyFrames { EnableDependentAnimation = true };
        var easing = new EasingDoubleKeyFrame { KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(200)), Value = _height };
        animation.KeyFrames.Add(easing);

        Storyboard.SetTargetProperty(animation, "(FrameworkElement.Height)");
        Storyboard.SetTarget(animation, _element);
        sb.Children.Add(animation);
    }
}

希望它可能会有所帮助