简体   繁体   中英

Resizing animation on SizeChanged event doesn't work as it should

I want a resizing animation when stackpanel visibility is set to visible state, but instead of that, I'm getting neverending flickering of border containing stackpanel.I don't think I'm doing it wrong. Stack panel contains an instance of TextBlock.

private void MyBorder_SizeChanged_1(object sender, SizeChangedEventArgs e)
{
    if (!first)
    {
        DoubleAnimation anim = new DoubleAnimation();
        anim.From = e.PreviousSize.Height;
        anim.To = e.NewSize.Height;
        anim.Duration = new Duration(TimeSpan.FromSeconds(1));
        Storyboard.SetTarget(anim, MyBorder);
        Storyboard.SetTargetProperty(anim, new PropertyPath(Border.HeightProperty));
        Storyboard st = new Storyboard();
        st.Children.Add(anim);
        st.Begin();
    }
    first = false;
}

private void MyBorder_Tap_1(object sender, GestureEventArgs e)
{
    if (MyPanel.Visibility == Visibility.Collapsed)
        MyPanel.Visibility = Visibility.Visible;
    else
        MyPanel.Visibility = Visibility.Collapsed;
}

The problem is that when you animate the height of the border it will trigger the SizeChanged event so you have a loop: size changed event>animate height>size changed event> ..
Also when the sized changed event is fired, the size change has already taken placed so even if that was working you will get a little flicking when it go back to do the animation.
Finally using HEight in an animation force a rendering update so that is not hardware accelerated. Probably the best would be to either do a Translate Transform or a Scale Transform.
For exemple you could do a scale transform between 0 and 1 directly on MyPanel in the tap event.

This might help you to. It is a work around

private void MyBorder_SizeChanged_1(object sender, SizeChangedEventArgs e)
    {
        if (!first)
        {
            DoubleAnimation anim = new DoubleAnimation();
            anim.From = e.PreviousSize.Height;
            anim.To = e.NewSize.Height;
            anim.Duration = new Duration(TimeSpan.FromSeconds(1));
            Storyboard.SetTarget(anim, MyBorder);
            Storyboard.SetTargetProperty(anim, new PropertyPath(Border.HeightProperty));
            Storyboard st = new Storyboard();
            st.Children.Add(anim);
            st.Completed += st_Completed;
            MyBorder.SizeChanged -= MyBorder_SizeChanged_1;
            st.Begin();

        }
        first = false;
    }

    void st_Completed(object sender, EventArgs e)
    {
        MyBorder.SizeChanged += MyBorder_SizeChanged_1;
    }

    private void MyBorder_Tap_1(object sender, GestureEventArgs e)
    {
        if (MyPanel.Visibility == Visibility.Collapsed)
            MyPanel.Visibility = Visibility.Visible;
        else
            MyPanel.Visibility = Visibility.Collapsed;


    }

With reference to the fact that border is getting resized even in the storyboard its better to remove the event of size changed. Try animating the parent container on chld size changed some thing kind of this

I've solved this problem. Silly my, I thought that Measure method of StackPanel is private, and didn't bother to make sure about it, here's solution code for expanding StackPanel on Click.

 private void MyBorder_Tap_1(object sender, GestureEventArgs e) { if (MyPanel.Visibility == Visibility.Collapsed) { MyPanel.Visibility = Visibility.Visible; MyPanel.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity)); DoubleAnimation anim = new DoubleAnimation(); anim.From = MyBorder.ActualHeight; anim.To = MyBorder.ActualHeight + MyPanel.DesiredSize.Height; anim.Duration = new Duration(TimeSpan.FromSeconds(0.25)); Storyboard.SetTarget(anim, MyBorder); Storyboard.SetTargetProperty(anim, new PropertyPath(Border.HeightProperty)); Storyboard st = new Storyboard(); st.Children.Add(anim); st.Begin(); } else { MyPanel.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity)); DoubleAnimation anim = new DoubleAnimation(); anim.From = MyBorder.ActualHeight; anim.To = MyBorder.ActualHeight - MyPanel.DesiredSize.Height; anim.Duration = new Duration(TimeSpan.FromSeconds(0.25)); Storyboard.SetTarget(anim, MyBorder); Storyboard.SetTargetProperty(anim, new PropertyPath(Border.HeightProperty)); Storyboard st = new Storyboard(); st.Children.Add(anim); st.Completed += (a,b) => { MyPanel.Visibility = Visibility.Collapsed; }; st.Begin(); } } 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM