141是可以同时动画的WPF面板项的最大数量吗?

我在C#中设计了几个动画Panel ,它们都是从一个基类inheritance的,它在Panel.Children上执行实际的动画。 直到最近,他们都完美地工作了…但是最近,我使用的是一个包含大量项目的集合,我开始得到一些奇怪的视觉错误。

当应用程序首次加载项目时,第一个x项目正确显示,然后剩余部分全部显示在第一个位置(彼此顶部)。 如果我调整窗口大小或选择一个项目,它们都会重新排列以便正确显示。 (使用下面的示例代码,您必须调整窗口大小才能看到它们自己正确。)

经过大量的讨论和调试,我发现正确的值仍然是每个项目的动画代码,但最后的x项根本没有动画。 每个项目肯定会通过动画代码,但最后的x项目保留在动画Panel.ArrangeOverride方法中设置的位置。

为了尝试在我的代码中找到问题,我创建了一个新的UserControl和动画Panel类,其中包含重新创建问题所需的最少代码。 这样做后,我很惊讶这个问题仍然可以重现。 在我的示例代码中有141个项目,没有显示问题,但不再显示问题。

请原谅长长的代码行,但有很多东西要显示。

AnimatedStackPanel.cs类

 public class AnimatedStackPanel : Panel { protected override Size MeasureOverride(Size availableSize) { double x = 0, y = 0; foreach (UIElement child in Children) { child.Measure(availableSize); x = Math.Max(x, availableSize.Width == double.PositiveInfinity ? child.DesiredSize.Width : availableSize.Width); y += child.DesiredSize.Height; } return new Size(availableSize.Width == double.PositiveInfinity ? x : availableSize.Width, availableSize.Height == double.PositiveInfinity ? y : availableSize.Height); } protected override Size ArrangeOverride(Size finalSize) { if (this.Children == null || this.Children.Count == 0) return finalSize; Size previousChildSize = new Size(); Point endPosition = new Point(0, 0); foreach (UIElement child in Children) { endPosition.Y += previousChildSize.Height; double childWidth = finalSize.Width; child.Arrange(new Rect(0, 0, childWidth, child.DesiredSize.Height)); Point startPosition = new Point(endPosition.X, endPosition.Y + finalSize.Height); AnimatePosition(child, startPosition, endPosition, new TimeSpan(0, 0, 1)); previousChildSize = child.DesiredSize; } return finalSize; } private void AnimatePosition(UIElement child, Point startPosition, Point endPosition, TimeSpan animationDuration) { DoubleAnimation xAnimation = new DoubleAnimation(startPosition.X, endPosition.X, animationDuration); DoubleAnimation yAnimation = new DoubleAnimation(startPosition.Y, endPosition.Y, animationDuration); TransformGroup transformGroup = child.RenderTransform as TransformGroup; if (transformGroup == null) { TranslateTransform translatationTransform = new TranslateTransform(); transformGroup = new TransformGroup(); transformGroup.Children.Add(translatationTransform); child.RenderTransform = transformGroup; child.RenderTransformOrigin = new Point(0, 0); } TranslateTransform translateTransform = (TranslateTransform)transformGroup.Children[0]; translateTransform.BeginAnimation(TranslateTransform.XProperty, xAnimation, HandoffBehavior.Compose); translateTransform.BeginAnimation(TranslateTransform.YProperty, yAnimation, HandoffBehavior.Compose); //child.Arrange(new Rect(endPosition.X, endPosition.Y, child.DesiredSize.Width, child.DesiredSize.Height)); } } 

AnimatedListBox.xaml UserControl

           

AnimatedListBox.xaml.cs后面的UserControl代码

 public partial class AnimatedListBox : UserControl { public AnimatedListBox() { InitializeComponent(); Data = new ObservableCollection(); // change this 150 below to anything less than 142 and the problem disappears!! for (int count = 1; count <= 150; count++) Data.Add(count); DataContext = this; } public static DependencyProperty DataProperty = DependencyProperty.Register("Data", typeof(ObservableCollection), typeof(AnimatedListBox)); public ObservableCollection Data { get { return (ObservableCollection)GetValue(DataProperty); } set { SetValue(DataProperty, value); } } } 

在进行实验时,我发现其他一些看似奇怪的东西。 如果我将Panel.ArrangeOverride方法中项目的位置更改为以下内容,则会有更多意外结果。

 child.Arrange(new Rect(endPosition.X, endPosition.Y, childWidth, child.DesiredSize.Height)); 

不知何故,这改变了实际(动画)结束位置,即。 物品最终被定位的地方。 它介绍了某种双重间距的物品。 如何在项目开始动画之前将项目排列到最终位置会改变其最终结束位置? 我错过了一些明显的东西吗

此外,如果您取消注释AnimatedStackPanel.AnimatePosition方法中的注释行并注释掉上面的两行(即剪切动画并将项目直接移动到动画将它们移动到的相同结束位置),那么您将看到问题再次消失……无论集合中有多少项目,这都适用。 这就是我认为问题与动画有关的原因。

我发现的最后一件事是,无论是否使用DataTemplate对于项目数据类型存在问题…我很确定它与动画有关。 如果有人能够看到我做错了什么,或者为此找到解决方案,我会非常感激,因为这让我感到困惑。 有人甚至可以用示例代码重现这个问题吗? 提前谢谢了。

谢里登,我玩了一下你的代码示例,我发现的是, 你应用RenderTransform 它显然很重要。 而不是在AnimatePosition中分配它,即在第一次运行ArrangeOverride期间,我将代码移动到MeasureOverride

 protected override Size MeasureOverride(Size availableSize) { double x = 0, y = 0; foreach (UIElement child in Children) { TransformGroup transformGroup = child.RenderTransform as TransformGroup; if (transformGroup == null) { TranslateTransform translatationTransform = new TranslateTransform(); transformGroup = new TransformGroup(); transformGroup.Children.Add(translatationTransform); child.RenderTransform = transformGroup; child.RenderTransformOrigin = new Point(0, 0); } child.Measure(availableSize); x = Math.Max(x, availableSize.Width == double.PositiveInfinity ? child.DesiredSize.Width : availableSize.Width); y += child.DesiredSize.Height; } return new Size( availableSize.Width == double.PositiveInfinity ? x : availableSize.Width, availableSize.Height == double.PositiveInfinity ? y : availableSize.Height); } 

现在,即使在第一次调用ArrangeOverride时,动画也会按预期运行。 看起来像最后几个RenderTransforms还没有附加到控件,而已经动画了。

顺便说一句,在运行32位Windows 7的两个不同系统(双核和四核)上,最大数量为144。