我终于设法让我的布局正确并且动画工作并且它不顺畅。它在中间有一个巨大的抖动/步骤。
我有一个使用StackPanel ItemsPanel的ListBox,ListBoxItems使用DataTemplate设置样式。这些项目是使用边框和可视笔刷进行反射的图像。
<UserControl x:Class="Thumbnails"
xmlns:local="clr-namespace:ContentPresenter"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
d:DesignHeight="350" d:DesignWidth="800">
<UserControl.Resources>
<local:ThumbImageHeightConverter x:Key="HeightConv" />
<local:ThumbImageWidthConverter x:Key="WidthConv" />
<local:InnerGridHeightConverter x:Key="InnerGridHeightConv" />
<local:ReflectWidthConverter x:Key="ReflectWidthConv" />
<local:ReflectCenterYConv x:Key="ReflectCenterYConv" />
<local:BorderThicknessScale x:Key="BorderThicknessScale" />
<local:BorderCornerRadiusScale x:Key="BorderCornerRadiusScale" />
<Storyboard x:Key="FadeUpAndFlash">
<!--<DoubleAnimation From="0" To="1" Storyboard.TargetProperty="(UIElement.Opacity)" Duration="0:0:10" FillBehavior="Stop" />-->
<DoubleAnimation From="0" To="1" Storyboard.TargetProperty="(UIElement.Opacity)" Duration="0:0:1" FillBehavior="Stop" />
</Storyboard>
<Storyboard x:Key="ReflectFadeUpAndFlash">
<!--<DoubleAnimation From="0" To="1" Storyboard.TargetProperty="(UIElement.Opacity)" Duration="0:0:10" FillBehavior="Stop" />-->
<DoubleAnimation From="0" To="0.75" Storyboard.TargetProperty="(UIElement.Opacity)" Duration="0:0:1" FillBehavior="Stop" />
</Storyboard>
<Style TargetType="{x:Type ListBox}">
<!-- Set the ItemTemplate of the ListBox to a DataTemplate which explains how to display an object of type BitmapImage. -->
<Style.Resources>
<!-- Background of selected item when focussed -->
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Black"/>
<!-- Background of selected item when not focussed -->
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Black" />
</Style.Resources>
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<Grid x:Name="ThumbGrid" VerticalAlignment="Top" Height="{Binding ElementName=ThumbListBox, Path=ActualHeight}" >
<Grid.RowDefinitions>
<RowDefinition x:Name="ThumbGridThumbImgRow" Height="80*" ></RowDefinition>
<RowDefinition x:Name="GridReflectRow" Height="20*" ></RowDefinition>
</Grid.RowDefinitions>
<Border x:Name="HighlightBorder" Padding="2" Margin="2" HorizontalAlignment="Center" VerticalAlignment="Center">
<Border.Style>
<Style TargetType="{x:Type Border}">
<Setter Property="BorderBrush" Value="Black"/>
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ListBoxItem}},Path=IsSelected}" Value="True">
<DataTrigger.Setters>
<Setter Property="BorderBrush" Value="Yellow"/>
</DataTrigger.Setters>
<DataTrigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource FadeUpAndFlash}" Name="AnimateImageBorder" />
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="AnimateImageBorder" />
</DataTrigger.ExitActions>
<!--<Setter Property="BorderBrush" Value="Yellow"/>-->
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<Border.Resources>
<sys:Int32 x:Key="HighlightBorderOrigRadius">18</sys:Int32>
</Border.Resources>
<Border.CornerRadius>
<MultiBinding Converter="{StaticResource BorderCornerRadiusScale}">
<Binding ElementName="HighlightBorder" Path="ActualWidth" />
<Binding Source="{StaticResource HighlightBorderOrigRadius}" />
</MultiBinding>
</Border.CornerRadius>
<Border.BorderThickness>
<MultiBinding Converter="{StaticResource BorderThicknessScale}">
<Binding ElementName="HighlightBorder" Path="ActualWidth" />
</MultiBinding>
</Border.BorderThickness>
<Grid x:Name="ThumbInnerGrid">
<Grid.Height>
<MultiBinding Converter="{StaticResource InnerGridHeightConv}">
<Binding ElementName="ThumbGrid" Path="ActualHeight" />
<Binding ElementName="HighlightBorder" Path="CornerRadius" />
<Binding ElementName="mask" Path="CornerRadius" />
</MultiBinding>
</Grid.Height>
<Border x:Name="mask" Background="Black">
<Border.Resources>
<sys:Int32 x:Key="MaskBorderOrigRadius">15</sys:Int32>
</Border.Resources>
<Border.CornerRadius>
<MultiBinding Converter="{StaticResource BorderCornerRadiusScale}">
<Binding ElementName="mask" Path="ActualWidth" />
<Binding Source="{StaticResource MaskBorderOrigRadius}" />
</MultiBinding>
</Border.CornerRadius>
</Border>
<StackPanel x:Name="ThumbInnerStack" VerticalAlignment="Top">
<StackPanel.OpacityMask>
<VisualBrush Visual="{Binding ElementName=mask}"/>
</StackPanel.OpacityMask>
<Image x:Name="ThumbImg" Stretch="UniformToFill" SnapsToDevicePixels="True" >
<Image.Height>
<MultiBinding Converter="{StaticResource HeightConv}">
<Binding ElementName="HighlightBorder" Path="ActualHeight" />
<Binding ElementName="HighlightBorder" Path="BorderThickness" />
<Binding ElementName="HighlightBorder" Path="Padding" />
</MultiBinding>
</Image.Height>
<Image.Width>
<MultiBinding Converter="{StaticResource WidthConv}">
<Binding ElementName="ThumbImg" Path="ActualHeight" />
<Binding ElementName="HighlightBorder" Path="BorderThickness" />
<Binding ElementName="HighlightBorder" Path="Padding" />
</MultiBinding>
</Image.Width>
<Image.Source>
<BitmapImage UriSource="{Binding Path=Src}"></BitmapImage>
</Image.Source>
</Image>
</StackPanel>
</Grid>
</Border>
<Border x:Name="ReflectBorder" Margin="0,-1,0,0" VerticalAlignment="Top" Height="{Binding ElementName=ThumbImg, Path=ActualHeight}" Grid.Row="1" SnapsToDevicePixels="True" Opacity="0.75" >
<Border.Style>
<Style TargetType="{x:Type Border}">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ListBoxItem}},Path=IsSelected}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource ReflectFadeUpAndFlash}" Name="AnimateImageReflection" />
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="AnimateImageReflection" />
</DataTrigger.ExitActions>
<!--<Setter Property="BorderBrush" Value="Yellow"/>-->
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<Border.Resources>
<sys:Int32 x:Key="MaskBorderOrigRadius">15</sys:Int32>
</Border.Resources>
<Border.CornerRadius>
<MultiBinding Converter="{StaticResource BorderCornerRadiusScale}">
<Binding ElementName="ReflectBorder" Path="ActualWidth" />
<Binding Source="{StaticResource MaskBorderOrigRadius}" />
</MultiBinding>
</Border.CornerRadius>
<Border.Width>
<MultiBinding Converter="{StaticResource ReflectWidthConv}">
<Binding ElementName="HighlightBorder" Path="ActualWidth" />
<Binding ElementName="HighlightBorder" Path="BorderThickness" />
</MultiBinding>
</Border.Width>
<Border.Background>
<VisualBrush Visual="{Binding ElementName=ThumbImg}">
<VisualBrush.Transform>
<ScaleTransform ScaleX="1" ScaleY="-1" CenterX="200">
<ScaleTransform.CenterY>
<MultiBinding Converter="{StaticResource ReflectCenterYConv}">
<Binding ElementName="ThumbImg" Path="ActualHeight" />
</MultiBinding>
</ScaleTransform.CenterY>
</ScaleTransform>
</VisualBrush.Transform>
</VisualBrush>
</Border.Background>
<Border.OpacityMask>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1.3">
<GradientStop Offset="0" Color="Black"></GradientStop>
<GradientStop Offset="0.15" Color="Transparent"></GradientStop>
</LinearGradientBrush>
</Border.OpacityMask>
</Border>
<Grid Grid.Row="1" MaxWidth="{Binding ElementName=ThumbImg, Path=ActualWidth}">
<Border Padding="10,0,10,25">
<Viewbox VerticalAlignment="Top" MaxWidth="{Binding ElementName=ThumbImg, Path=ActualWidth}">
<Label x:Name="ThumbTitle" Margin="0,-5,0,0" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Top" Content="{Binding Path=Title}" FontFamily="Arial" Foreground="White" />
</Viewbox>
</Border>
</Grid>
</Grid>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel x:Name="ThumbListStack" Orientation="Horizontal" Loaded="StackPanel_Loaded">
<StackPanel.RenderTransform>
<TranslateTransform X="0" Y="0" />
</StackPanel.RenderTransform>
</StackPanel>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled" />
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Disabled" />
<Setter Property="Background" Value="Black"/>
</Style>
</UserControl.Resources>
<UserControl.DataContext>
<ObjectDataProvider ObjectType="{x:Type local:ThumbImageLoader}" MethodName="LoadImagesv2" IsAsynchronous="True" />
</UserControl.DataContext>
<!-- This ListBox is the Content of the Window. Normally you would have a panel of some type as the Window's Content, but let's keep it simple. -->
<Grid x:Name="ThumbListBoxGrid">
<ListBox x:Name="ThumbListBox" ItemsSource="{Binding}" VerticalAlignment="Top" Height="{Binding ElementName=ThumbListBoxGrid, Path=ActualHeight}" IsSynchronizedWithCurrentItem="True" />
</Grid>
以下是控制TranslateTransform动画的代码隐藏:
RenderTransform = New TranslateTransform()
Dim d As New Duration(New TimeSpan(0, 0, 0, 1, 30))
Dim x As New DoubleAnimation(translatePosition.X, d)
x.EasingFunction = New PowerEase() With {.EasingMode = EasingMode.EaseInOut, .Power = 4}
Storyboard.SetTarget(x, m_itemsPanelStackPanel)
Storyboard.SetTargetProperty(x, New PropertyPath("(StackPanel.RenderTransform).(TranslateTransform.X)"))
Timeline.SetDesiredFrameRate(x, 120)
'Storyboard.SetDesiredFrameRate(x, 120) 'have tried setting the FrameRate both ways
Dim sb As New Storyboard()
sb.Children.Add(x)
sb.Begin()
我试过禁用Ease但没有改进。
TranslateTransform是否存在已知问题?
我还能做些什么来提高性能吗?有没有更好的方法来设置x轴的动画以使列表框中的图像水平滚动?