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

发布于 2024-07-09 17:59:46 字数 750 浏览 5 评论 0原文

我想在双击列表框中的项目时创建视觉效果。 到目前为止,我具有拖放功能,其中项目在视觉上附加到鼠标,并且可以移动到放置目标。 通过该功能,我可以使用获取项目容器的相同逻辑为项目设置动画,但是我无法离开项目控制。 有没有办法从列表框中删除该项目并将其以视觉方式动画到另一个位置? 基本上,主列表框是一手牌。 双击卡片时,我希望它在视觉上从手牌列表框移动到丢弃列表框。 到目前为止,将项目从一个集合移动到另一个集合的逻辑没有问题,但是我真的很想要此事件的动画视觉表示。 任何关于如何做这样的事情的想法或参考将不胜感激。

谢谢, 布兰登

关于我尝试过的进一步细节: 有一些概念我还没有掌握得很清楚,这导致我撞到了这堵墙。 我有一个方法,将 ListBox 作为 ItemsControl 传入(有些可能是不必要的)、作为列表框项的 FrameworkElement 以及与 ListBox 项关联的数据对象。 我试图做的是作为画布的 ListBoxItem 的 FindVisualChild 。 我能做到。 在我看来,我想以某种方式将画布克隆为画布或位图,将其添加到同一位置的页面子项的子项中,从 ListBox 中删除 ListBoxItem,并将克隆动画设置为丢弃桩。 当动画完成时,克隆将被删除或隐藏,并且当该对象被添加到丢弃堆集合时,它将有效地替换克隆。

我的问题是,我觉得确实有一种更简单的方法可以使用装饰层或其他东西来做到这一点。 我也不知道如何将克隆定位在视觉树上元素中的完全相同的位置。 我将继续努力并研究其他方法,我只是希望有人能分享一些对此的见解。

I would like to create a visual effect when an item in a listbox is double clicked. So far I have drag and drop functionality where the item is visually attached to the mouse and can be moved to a drop target. From that functionality I am able to animate the item using the same logic of getting the item container, however I am not able to leave the items control. Is there any way to remove the item from the ListBox and visually animate it to another location? Basically the main list box is a hand of cards. When a card is double-clicked I want it to visually move from the hand listbox to a discard listbox. As of now, the logic for moving the item from one collection to another is no problem, however I would really like an animated visual representation of this event. Any ideas or references on how to do something like this would be appreciated.

Thanks,
Brandon

Further Details on what I have attempted:
There are some concepts that I do not yet have a strong grasp of yet, which has led me to run face first into this wall. I have a method that I pass in(some may be unnecessary) the ListBox as an ItemsControl, a FrameworkElement that is the listbox item, and the data object associated with the ListBox item. What I attempted to do was FindVisualChild of the ListBoxItem that is a canvas. I can do that. In my mind I was wanting to somehow clone the canvas either as a canvas or as a bitmap, add it to the children of the child of the page in the same location, remove the ListBoxItem from the ListBox, and animate the clone to the discard pile. When the animation completes the clone will be removed or hidden, and as that object is added to the discard pile collection it will effectively take the replace the clone.

My problem with this, is that I feel like there really is a simpler way of doing this using the adorner layer or something. I also, don't know how I would position the clone at the exact same position in the element further up the visual tree. I am going to keep working on it and researching other approaches, and I will just hope that someone will share some insight on this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

是伱的 2024-07-16 17:59:46

这是我编写的一些代码,用于将视觉效果绘制到位图。 您可以根据您的需要进行调整,并通过装饰代表两个列表视图的共同祖先的 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;
        }

Here's some code I worked up to draw a visual to a bitmap. You may be able to adapt this to your needs, and draw the bitmap by adorning the UIElement that represents a common ancestor of the two list views. Note the use of FrameworkElement.TransformToAncestor to get the coordinates of a nested element in terms of an ancestor element.

        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;
        }
红衣飘飘貌似仙 2024-07-16 17:59:46

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

OK, you could try taking a Visual element and setting it's background to a visualbrush of your ListItem and animate that to the other list box. You can wait for the storyboard completed event to actually do the switch. If this were me, I would animate from one box only to the edge of the other. If the switch happens fast enough it should look pretty seamless to the user. Finding the exact position of where the item is supposed to go into the list box would be pretty complex based on any sorting/filtering rules you have.

家住魔仙堡 2024-07-16 17:59:46

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

If the two listboxes are always in the same position, you could try animating the double-clicked item to a predetermined spot, let's say half-way between the old list and the new list. Then execute the code to move the item to the new list, but use a style that immediately starts an animation on that item starting it from that predetermined location and animating to its location in the new list. You'd probably have to tweak the initial offset of the new item at runtime based on where it's inserted in the list.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文