views:

1355

answers:

4

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.

+1  A: 

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.

Nick
+1  A: 

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.

Ben Reierson
+1  A: 

This may not help you completely but as an idea may help you along. http://bea.stollnitz.com/blog/?p=53

Ray Booysen
I used some of these concepts for implementing the ability to drag and drop. After achieving that behavior I decided that I also wanted to be able to double click the item triggering an animation to the other ListBox. The answer below is similar to how I got it working.
BrandonS
+1  A: 

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;
        }
jlew
This is very similar to how I was able to get this idea to work the way that I had intended. Once I rendered a bitmap of the item, I was able to animate it to the fixed location of the destination listbox.
BrandonS