简体   繁体   English

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

[英]Is 141 the maximum number of WPF panel items that can be animated simultaneously?

I have designed several animated Panel s in C# that all inherit from one base class that performs the actual animations on the Panel.Children . 我在C#中设计了几个动画Panel ,它们都继承自一个在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. 直到最近,他们都完美地工作了...但最近,我使用的是一个包含大量物品的集合,我开始得到一些奇怪的视觉错误。

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). 当应用程序首次加载项目时,第一个x项目正确显示,然后其余部分全部显示在第一个位置(彼此顶部)。 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.) (使用下面的示例代码,您必须调整窗口大小才能看到它们自己正确。)

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. 经过大量的讨论和调试后,我发现正确的值仍然是每个项目的动画代码,但最后的x项根本没有动画。 Each item definitely passes through the animation code, but the last x items stay in the position set in the animated Panel.ArrangeOverride method. 每个项目肯定会通过动画代码,但最后的x项目保留在动画Panel.ArrangeOverride方法中设置的位置。

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. 为了尝试在我的代码中找到问题,我创建了一个新的UserControl和动画Panel类,其中包含重新创建问题所需的最少代码。 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. 在我的示例代码中有141个项目,没有显示问题,但是现在出现了问题。

Please excuse the long lines of code, but there is so much to display. 请原谅长长的代码行,但有很多东西要显示。

AnimatedStackPanel.cs class 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 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 UserControl code behind AnimatedListBox.xaml.cs后面的UserControl代码

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); }
    }
}

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. 如果我将Panel.ArrangeOverride方法中项目的位置更改为以下内容,则会有更多意外结果。

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? 我错过了一些明显的东西吗

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. 此外,如果您取消注释AnimatedStackPanel.AnimatePosition方法中的注释行并注释掉上面的两行(即剪切动画并将项目直接移动到动画将它们移动到的相同结束位置),那么您将看到问题再次消失......无论集合中有多少项,这都适用。 This is what led me to think that the problem was animation related. 这就是我认为这个问题与动画有关的原因。

One last thing that I found out is that the problem exists with or without using DataTemplate s for the item data type... I'm pretty sure that it's animation related. 我发现的最后一件事是,对于项目数据类型,使用或不使用DataTemplate存在问题...我很确定它与动画有关。 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. 提前谢谢了。

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. Sheridan,我玩了你的代码示例,我发现的是, 你应用RenderTransform 它显然很重要。 Instead of assigning it in AnimatePosition , ie during the first run of ArrangeOverride, i moved the code to MeasureOverride : 而不是在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);
}

Now the animations behave as expected even on the first invocation of ArrangeOverride. 现在,即使在第一次调用ArrangeOverride时,动画也会按预期运行。 Seems like the last few RenderTransforms were not yet attached to the control while already beeing animated. 看起来像最后几个RenderTransforms还没有附加到控件上,同时已经动画了。

By the way, the maximum number was 144 for me on two different systems (dual core and quad core) running 32-bit Windows 7. 顺便说一句,在运行32位Windows 7的两个不同系统(双核和四核)上,最大数量为144。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 我可以同时旋转最大数量的Awesomium WebCores吗? - Maximum number of Awesomium WebCores can i spin simultaneously? 包装面板项目分隔符WPF - Wrap Panel Items Separator WPF ASP.NET Core WebAPI可以同时处理的最大请求数量是多少? - What is the maximum number of requests that ASP.NET Core WebAPI can handle simultaneously? 如何在WPF中隐藏面板后面的项目 - how to hide items behind a panel in wpf 在WPF中使用面板中的选定项目填充面板 - Populating a panel with selected items from a grid in WPF Outlook 加载项崩溃或您的服务器管理员限制了您可以同时打开的项目数 - Outlook Add-In Crashes or Your server administrator has limited the number of items you can open simultaneously 如何重现:您的服务器管理员限制了您可以同时打开的项目数量 - How to reproduce: Your server administrator has limited the number of items you can open simultaneously 以LINQ方式返回最大数量的项目 - Returning a maximum number of items the LINQ way Linq:如何按最大项目数进行分组 - Linq: How to group by maximum number of items WCF错误-“可以在对象图中序列化或反序列化的最大项目数为&#39;65536” - WCF Error - 'Maximum number of items that can be serialized or deserialized in an object graph is '65536'
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM