C# 141是可以同时设置动画的WPF面板项目的最大数量吗?
我用C语言设计了几个动画的C# 141是可以同时设置动画的WPF面板项目的最大数量吗?,c#,wpf,animation,panel,C#,Wpf,Animation,Panel,我用C语言设计了几个动画的面板s,它们都继承自一个基类,该基类在面板上执行实际动画。子类。直到最近,他们都工作得很好。。。但最近,我在一个集合中使用了一个包含大量项目的集合,我开始出现一些奇怪的视觉错误 当应用程序第一次加载项目时,第一个x数量的项目将正确显示,然后剩余的项目将全部显示在第一个位置(相互重叠)。如果我调整窗口大小或选择一个项目,它们都会重新排列以正确显示。(使用下面的示例代码,您必须调整窗口的大小,以查看它们是否正确。) 经过大量的抓头和调试后,我发现每个项目的动画代码中仍然有正
面板
s,它们都继承自一个基类,该基类在面板上执行实际动画。子类
。直到最近,他们都工作得很好。。。但最近,我在一个集合中使用了一个包含大量项目的集合,我开始出现一些奇怪的视觉错误
当应用程序第一次加载项目时,第一个x数量的项目将正确显示,然后剩余的项目将全部显示在第一个位置(相互重叠)。如果我调整窗口大小或选择一个项目,它们都会重新排列以正确显示。(使用下面的示例代码,您必须调整窗口的大小,以查看它们是否正确。)
经过大量的抓头和调试后,我发现每个项目的动画代码中仍然有正确的值,但最后的x个项目根本没有动画。每个项目都肯定会通过动画代码,但最后的x个项目保留在动画面板中设置的位置。ArrangeOverride
方法
为了在我的代码中找到问题,我创建了一个新的UserControl
和动画Panel
类,用最少的代码重新创建问题。这样做之后,我很惊讶这个问题仍然可以重现。对于我的示例代码中的141项,没有显示问题,但是对于更多项,问题就出现了
请原谅代码排得太长,但是有太多的东西要显示
动画StackPanel.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.xamlUserControl
<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>
在实验中,我发现了一些奇怪的东西。如果我将面板.ArrangeOverride
方法中项目的位置更改为以下值,则会出现更多意外结果
child.Arrange(new Rect(endPosition.X, endPosition.Y, childWidth, child.DesiredSize.Height));
不知何故,这会更改实际(动画)结束位置,即项目结束时的位置。它引入了一些项目的双重间距。在项目开始其动画之前,将项目安排在其结束位置如何更改其最终结束位置?我错过了什么明显的东西吗
此外,如果在AnimatedStackPanel.AnimatePosition
方法中取消注释注释注释行,并注释掉上面的两行(即,剪切动画并将项目直接移动到动画将移动到的相同末端位置),则您将看到问题再次消失。。。无论集合中有多少项,这都适用。这就是为什么我认为这个问题与动画有关
我发现的最后一件事是,对于项数据类型使用或不使用
DataTemplate
s都存在问题。。。我很确定这与动画有关。如果有人能看到我做错了什么,或者找到解决办法,我会非常感激,因为这件事让我感到困惑。有人能用示例代码重现这个问题吗?非常感谢。Sheridan,我对您的代码示例进行了一些研究,我发现当您应用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个。就我而言,额外+1也是如此!做得好!你到底是怎么计算出来的?另外,我想知道项目的最大数量,因为以前,我的项目数量大约是110个。报告:在64位Windows 8.1双核上,最大数量是144个
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);
}