141是可以同时进行动画WPF面板项目的最大数量? [英] Is 141 the maximum number of WPF panel items that can be animated simultaneously?

查看:153
本文介绍了141是可以同时进行动画WPF面板项目的最大数量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我设计了几个动画面板 S IN C#中,所有来自于 Panel.Children 。直到最近,他们都非常完美......但最近,我用一用一集,里面有大量的项目,我开始变得有些奇怪的视觉误差。

I have designed several animated Panels in C# that all inherit from one base class that performs the actual animations on the Panel.Children. Up until recently, they've all worked perfectly... but recently, I was using one with a collection that had a large number of items in it and I started getting some strange visual errors.

当应用程序首次加载的物品,物品的第一x个正确显示,然后将其余的都在第一位置上显示(在彼此的顶部)。如果我调整窗口大小或选择一个项目,他们都重新安排自己正确显示。 (使用例如code下面,你将不得不调整窗口看到他们改正自己。)

When the application first loads the items, the first x number of items display correctly and then the remainder are all displayed in the first position (on top of each other). If I resize the window or select an item, they all rearrange themselves to display correctly. (Using the example code below, you will have to resize the window to see them correct themselves.)

大量的头划伤和调试后,我发现,正确的价值观仍然通过对动画code为每个项目获得的,但根本就没有被动画的最后x项目。每个项目肯定通过动画code通过,但最后x物品留在设定的位置动画 Panel.ArrangeOverride 方法。

After a lot of head scratching and debugging, I discovered that the correct values were still getting through to the animation code for each item, but the last x items were simply not being animated. Each item definitely passes through the animation code, but the last x items stay in the position set in the animated Panel.ArrangeOverride method.

为了尽量在我的code来查找问题,我创建了一个新的用户控件和动画面板类来重现问题所需的最少code。做如此,我很惊讶,这个问题仍然是重复的。在我的例子code 141项,没有显示问题,但更多的,问题出现了。

In order to try to locate a problem in my code, I created a new UserControl and animated Panel class with the minimum code required to recreate the problem. Having done so, I was surprised that the problem was still reproducible. With 141 items in my example code, there was no display problem, but with any more, the problem appears.

请原谅code的长队,但有这么多的显示。

Please excuse the long lines of code, but there is so much to display.

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 用户控件

AnimatedListBox.xaml UserControl

<UserControl x:Class="WpfTest.Views.AnimatedListBox"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:Controls="clr-namespace:WpfTest.Views.Controls">
    <UserControl.Resources>
        <ItemsPanelTemplate x:Key="AnimatedStackPanel">
            <Controls:AnimatedStackPanel />
        </ItemsPanelTemplate>
    </UserControl.Resources>
    <Grid>
        <ListBox ItemsSource="{Binding Data}" ItemsPanel="{StaticResource AnimatedStackPanel}" ScrollViewer.HorizontalScrollBarVisibility="Disabled" />
    </Grid>
</UserControl>

AnimatedListBox.xaml.cs 用户控件 code后面

AnimatedListBox.xaml.cs UserControl code behind

public partial class AnimatedListBox : UserControl
{
    public AnimatedListBox()
    {
        InitializeComponent();
        Data = new ObservableCollection<int>();
        // 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<int>), typeof(AnimatedListBox));

    public ObservableCollection<int> Data
    {
        get { return (ObservableCollection<int>)GetValue(DataProperty); }
        set { SetValue(DataProperty, value); }
    }
}

虽然实验,我发现别的东西似乎有些奇怪。如果我更改项目的位置 Panel.ArrangeOverride 方法下,有更多的意想不到的效果。

While experimenting, I found something else that seems strange. If I change the position of the item in the Panel.ArrangeOverride method to the following, there are more unexpected results.

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

不知何故,这将改变实际(动画)末端位置,即得。其中项目最终被定位。它引入了一些项目的双间距。如何安排其末端位置的项目启动其动画改变其最后的最后位置之前?我失去了一些东西明显?

Somehow, this changes the actual (animation) end positions, ie. where the items end up being positioned. It introduces some kind of double spacing of the items. How can arranging the item in its end position before it starts its animation change its final end position? Am I missing something obvious?

此外,如果您取消注释在 AnimatedStackPanel.AnimatePosition 方法注释行及以上注释掉两行(即切出的动画和直接移动的项目该动画将移动他们),那么你会看到问题的同一端位置再次消失......这适用无论多少个项都收藏。这是促使我认为这个问题是相关的动画

Also, if you uncomment the commented line in the AnimatedStackPanel.AnimatePosition method and comment out the two lines above (ie. cut out the animation and move the items directly to the same end positions that the animations would have moved them to) then you will see the problem disappear again... this applies no matter how many items are in the collection. This is what led me to think that the problem was animation related.

这是我发现的最后一件事是,使用或不使用的DataTemplate 取值存在的项目数据类型的问题......我pretty确定它的动画相关。如果任何人都可以看到我在做什么错了,还是找到了一个解决方案,我会非常感激,因为这一块已经有我百思不得其解。任何人都可以甚至重现此问题的例子code?提前很多感谢。

One last thing that I found out is that the problem exists with or without using DataTemplates for the item data type... I'm pretty sure that it's animation related. If anyone can see what I'm doing wrong, or find a solution for this, I'd be very grateful because this one has had me baffled. Can anyone even reproduce this problem with the example code? Many thanks in advance.

推荐答案

谢里丹,我与你的code样品有点发挥四周,我发现了什么是它显然是重要的您应用的RenderTransform。相反ArrangeOverride的第一次运行过程中 AnimatePosition 分配给它,即,我搬到了code到的MeasureOverride

Sheridan, i played around with your code sample a bit and what i found out is that it apparently matters when you apply the RenderTransform. Instead of assigning it in AnimatePosition, i.e. during the first run of ArrangeOverride, i moved the code to 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还没有被附着,而已经beeing动画控制。

Now the animations behave as expected even on the first invocation of ArrangeOverride. Seems like the last few RenderTransforms were not yet attached to the control while already beeing animated.

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

By the way, the maximum number was 144 for me on two different systems (dual core and quad core) running 32-bit Windows 7.

这篇关于141是可以同时进行动画WPF面板项目的最大数量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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