将ListBoxItem从一个ListBox动画到另一个ListBox

时间:2008-12-17 16:38:00

标签: wpf animation listboxitem

我想在双击列表框中的项目时创建视觉效果。到目前为止,我有拖放功能,其中项目可视地连接到鼠标,并可以移动到放置目标。从该功能,我能够使用获取项容器的相同逻辑来动画项目,但是我无法保留项目控件。有没有办法从ListBox中删除该项目并在视觉上将其动画到另一个位置?基本上主要的列表框是一手牌。当双击一张卡时,我希望它可以从手动列表框直观地移动到丢弃列表框。截至目前,将项目从一个集合移动到另一个集合的逻辑没有问题,但我真的很喜欢这个事件的动画视觉表示。任何有关如何做这样的事情的想法或参考将不胜感激。

谢谢, 布兰登

有关我的尝试的进一步详情: 还有一些我尚未掌握的概念,这使我首先进入了这面墙。我有一个方法,我传入(有些可能是不必要的)ListBox作为ItemsControl,FrameworkElement是列表框项,以及与ListBox项关联的数据对象。我试图做的是作为画布的ListBoxItem的FindVisualChild。我能做到。在我看来,我想以某种方式将画布克隆为画布或位图,将其添加到同一位置的页面子节点的子节点,从ListBox中删除ListBoxItem,并将克隆动画为discard桩。当动画完成时,将删除或隐藏克隆,并且当该对象被添加到discard桩集合时,它将有效地替换克隆。

我的问题是,我觉得使用adorner层或其他东西真的有更简单的方法。我也不知道如何将克隆放置在视觉树上的元素中的完全相同的位置。我将继续努力并研究其他方法,我希望有人能就此分享一些见解。

3 个答案:

答案 0 :(得分:1)

好的,您可以尝试使用Visual元素并将其背景设置为ListItem的可视化工具,并将其设置为另一个列表框的动画。您可以等待故事板完成事件实际进行切换。如果这是我,我会从一个盒子动画到另一个盒子的边缘。如果切换发生得足够快,它应该看起来对用户来说非常无缝。根据您的任何排序/过滤规则,找到项目应该进入列表框的确切位置将非常复杂。

答案 1 :(得分:1)

如果两个列表框始终处于相同位置,您可以尝试将双击项目设置为预定位置,让我们说旧列表和新列表之间的中间位置。然后执行代码将项目移动到新列表,但使用一种样式,该样式立即在该项目上启动动画,从该预定位置开始动画,并动画到新列表中的位置。您可能必须根据新项目在列表中的插入位置调整新项目的初始偏移量。

答案 2 :(得分:1)

这是我编写的一些代码,用于为位图绘制视觉效果。您可以根据需要调整它,并通过装饰代表两个列表视图的共同祖先的UIElement来绘制位图。请注意使用FrameworkElement.TransformToAncestor以祖先元素的形式获取嵌套元素的坐标。

        public static BitmapSource CreateBitmapFromElement(FrameworkElement element, Double dpiX, Double dpiY)
        {
            Size elementSize = new Size(element.ActualWidth, element.ActualHeight);
            Visual root = GetAdornerDecoratorAncestor(element);
            Rect elementBounds  = element.TransformToAncestor(root).TransformBounds(new Rect(elementSize));

            RenderTargetBitmap rtb = new RenderTargetBitmap((Int32)(elementBounds.Size.Width * dpiX / 96.0),
                                           (Int32)(elementBounds.Size.Height * dpiY / 96.0),
                                           dpiX,
                                           dpiY,
                                           PixelFormats.Pbgra32);

            DrawingVisual dv = new DrawingVisual();
            using (DrawingContext dc = dv.RenderOpen())
            {
                VisualBrush vb = new VisualBrush(root);
                vb.ViewboxUnits = BrushMappingMode.Absolute;
                vb.Stretch = Stretch.None;
                vb.Viewbox = elementBounds;
                dc.DrawRectangle(vb, null, new Rect(new Point(), elementBounds.Size));
            }
            rtb.Render(dv);
            return rtb;
        }

        public static Visual GetAdornerDecoratorAncestor(DependencyObject obj)
        {            
            while(obj != null && !(obj is AdornerDecorator))
            {
                obj = VisualTreeHelper.GetParent(obj);
            }
            return obj as AdornerDecorator;
        }