我有一个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之间变化。但我希望在不必硬编码高度的情况下实现更可重用的解决方案。
任何帮助将不胜感激。 谢谢!
答案 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);
}
}
希望它可能会有所帮助