Removing FrameworkElements on Animation Completion

佐手、 提交于 2019-12-11 10:47:39

问题


I've been teaching myself WPF through Sells/Griffiths' "Programming WPF", and I've found it a great resource, but I'm trying to take some of the concepts they've introduced me to and go a step further, and I'm running into a conceptual snag on how to put the pieces together to accomplish what I'm trying to do.

In this exercise, I'm trying to create self-terminating animations; FrameworkElements that are created by Events, perform an animation, and then delete themselves. I'm having problems figuring out how to call back to the parent FrameworkElement from the animation.Completed event.

I asked this question originally just using DoubleAnimations that were uncontained and not part of the Storyboard. I have since added the Storyboard, and made the Storyboard and rectangle resources so they can be reused easily.

Here's what I have so far:
.xaml:

<Window.Resources>
    <Storyboard x:Key="GrowSquare" x:Shared="False">
        <DoubleAnimation Storyboard.TargetProperty="(Canvas.Top)" By="-50" Duration="0:0:2"/>
        <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" By="-50" Duration="0:0:2"/>
        <DoubleAnimation Storyboard.TargetProperty="(Ellipse.Width)" By="100" Duration="0:0:2"/>
        <DoubleAnimation Storyboard.TargetProperty="(Ellipse.Height)" By="100" Duration="0:0:2"/>
    </Storyboard>
    <Rectangle x:Key="MyRect" x:Shared="False" Width="20" Height="20">
    </Rectangle>
</Window.Resources>
<Canvas x:Name="myCanvas" MouseMove="myCanvas_MouseMove" Background="White"/>

.cs:

public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
            lastFire = DateTime.Now;
        }

        DateTime lastFire;

        private void myCanvas_MouseMove(object sender, MouseEventArgs e)
        {
            DateTime nowTime = DateTime.Now;
            TimeSpan T = nowTime.Subtract(lastFire);

            if (T.TotalMilliseconds > 200)
            {
                lastFire = nowTime;
                Random Rand = new Random();

                Rectangle myRect = (Rectangle)FindResource("MyRect");
                myRect.Fill = new SolidColorBrush(Color.FromRgb((byte)Rand.Next(256), (byte)Rand.Next(256), (byte)Rand.Next(256)));
                Point myLoc = e.GetPosition(myCanvas);
                Canvas.SetLeft(myRect, myLoc.X - 10);
                Canvas.SetTop(myRect, myLoc.Y - 10);
                myCanvas.Children.Add(myRect);

                Storyboard SB = (Storyboard)FindResource("GrowSquare");
                SB.Completed += new EventHandler(SB_Completed);
                SB.Begin(myRect);
            }

        }

        void SB_Completed(object sender, EventArgs e)
        {
            myCanvas.Children.RemoveAt(0);
        }
    }

This works, but not in the way I'd like it. Since the canvas is empty, and all animations are the same length, when an animation finishes, it will always be the one that was called on the first child of the canvas.

However, I'd like to implement animaitons that take a random amount of time, meaning that animations will not always start and end in the same order. Somehow in the SB_Completed event, I'd like to access the control that it was being called upon, but I can't seem to find the path to it yet.

Is there a way to get from the Media.Animation.ClockGroup that calls the SB_Completed event to the control that the animation is being called on?


回答1:


change the line where you assign the event handler to this:

SB.Completed += (s,e) => myCanvas.Children.Remove(myRect);


来源:https://stackoverflow.com/questions/778795/removing-frameworkelements-on-animation-completion

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!