0
votes

In my app I have A grid with visibility bound to a property in the view model.

What I want to do is when the visibility property changes at the view model, the grid fades in or out according to the visibility value: Visible/Collapsed.

how can I achieve this ?

2
What are you struggling with? Listening to a property change? The animation? The fact that collapsing is immediately in effect? - HDW Production
Yes, I don't want it to collapse immediately, I want it to fade in/out as the visibility property changes - Mina Wissa
In that case you have to made storyboards for the two states and has to run them and after completion of each storyboard you have to set the property to its value. - loop
@loop ok, how can I listen to the change in the visibility property, knowing that the storyboards will be defined in the page's XAML/Code behind, not in the view model - Mina Wissa
What i have done is all workaround. In the setter of the Property you have send a message to the view and in the message receiving event i run the storyboard and in its completion i set the property. and in the setter of the property i had made a check of !=PreviousValue. I used mvvm Messenger Class. - loop

2 Answers

4
votes

Inspired by the answer of "HDW Production", here's the code for Windows Store and Windows Phone Store apps:

public class FadingVisibilityGrid : Grid
{
    public static readonly DependencyProperty DeferredVisibilityProperty = DependencyProperty.Register(
        "DeferredVisibility", typeof (Visibility), typeof (FadingVisibilityGrid), new PropertyMetadata(default(Visibility), DeferredVisibilityChanged));

    private static void DeferredVisibilityChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        var newVisibility = (Visibility)e.NewValue;
        var grid = (FadingVisibilityGrid)sender;


        var animation = new DoubleAnimation
        {
            Duration = new Duration(TimeSpan.FromMilliseconds(200))
        };
        Storyboard.SetTarget(animation, grid);
        Storyboard.SetTargetProperty(animation, "Grid.Opacity");
        grid.FadeStoryBoard.Stop();
        grid.FadeStoryBoard = new Storyboard();
        grid.FadeStoryBoard.Children.Add(animation);

        if (newVisibility == Visibility.Visible)
        {
            animation.From = 0;
            animation.To = 1;
            grid.Visibility = Visibility.Visible;
            grid.FadeStoryBoard.Begin();
        }
        else
        {
            animation.From = 1;
            animation.To = 0;
            grid.FadeStoryBoard.Completed += (o, o1) =>
            {
                grid.Visibility = newVisibility;
            };
            grid.FadeStoryBoard.Begin();
        }

    }

    public Visibility DeferredVisibility
    {
        get { return (Visibility) GetValue(DeferredVisibilityProperty); }
        set { SetValue(DeferredVisibilityProperty, value); }
    }

    private Storyboard _fadeStoryBoard = new Storyboard();

    public Storyboard FadeStoryBoard
    {
        get { return _fadeStoryBoard; }
        set { _fadeStoryBoard = value; }
    }
}
0
votes

You need a new DependencyProperty, either by inheriting from Grid and adding one or by creating an attached property. Let's call it DeferredVisibility and let it be of type Visibility.

When DeferredVisibility is changed to Visible, set the Visibility to Visible and animate the opacity from 0 to 1.

When DeferredVisibility is changed to Collapsed, animate the opacity from 1 to 0 and THEN set the Visibility to Collapsed.