WPF Animate Window Visibility Change

2019-02-14 17:37发布

问题:

I'm trying to figure out how to animate the change from Visibile to Hidden for a WPF window. The way I currently have the application working is that the window is normally hidden and when I move the mouse to the side of the screen it pops out, I'm using a boolean to visibility converter to do that but what I would like to do is to have the application slide out more smoothly on mouse over as well as slide back in again afterwards.

I haven't don't anything with animations so I'm not sure how to do this. Firstly I'm not really sure what animation I should use the do this, secondly I'm not really sure whether I should trigger this on the "IsWindowVisibile" property in the viewmodel or if I should bind it to the VisibilityChanged event and thirdly I'm not sure if this is possible when the window size is variable.

[Edit]

If necessary I will 'take' an opacity solution but that's not exactly the 'sliding' effect I am trying to get.

回答1:

I did something like that (opacity goes to 0 during 2 seconds and window hides): just look at code, it's simple

MainWindow.xaml:

    <Storyboard x:Key="hideMe">
        <DoubleAnimation Storyboard.TargetProperty="Opacity" Duration="0:0:2" To="0.0"/>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility">
            <DiscreteObjectKeyFrame KeyTime="0:0:2" Value="{x:Static Visibility.Hidden}"/>
        </ObjectAnimationUsingKeyFrames>
    </Storyboard>
    <Storyboard x:Key="showMe">
        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility">
            <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Visible}"/>
        </ObjectAnimationUsingKeyFrames>
        <DoubleAnimation Storyboard.TargetProperty="Opacity" Duration="0:0:5" To="0.75"/>
    </Storyboard>

MainWindow.xaml.cs

    public void ShowMe() {
        (FindResource("showMe") as Storyboard).Begin(this);
    }
    public void HideMe() {
        (FindResource("hideMe") as Storyboard).Begin(this);
    }

Just call HideMe() or ShowMe() instead of setting Visibility = Visibility.Hidden in code

Edit

WPF is slow when moving windows, so if you need sliding animation:

  1. Make a transparent window (AllowsTransparency="True" Background="Transparent" WindowStyle="None")

  2. Put all your controls onto opaque panel (Background="{StaticResource {x:Static SystemColors.ControlBrushKey}}")

  3. Animate this panel's Margin.Left from 0 to window's ActualWidth, then hide a window - this will remove a problem of saving window size



回答2:

Playing with a Window's Opacity/Visibility requires a simple DoubleAnimation.

Example:

IsVisibleChanged += new DependencyPropertyChangedEventHandler(MainWindow_IsVisibleChanged);

void MainWindow_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
    DoubleAnimation da = new DoubleAnimation()
    {
        From = (IsVisible) ? 0 : 1,
        To = (IsVisible) ? 1 : 0,
        Duration = TimeSpan.FromSeconds(1)
    };

    BeginAnimation(Window.OpacityProperty, da);
}

Problem:

For this to work as expected, you need to set AllowsTransparency to True on your window. If you don't set this, your window with Opacity set to 0 will be Black.

The problem is for this property to be True, you need to have WindowStyle as None. Which means no frame around your window. That means no close, minimize, maximize, restore, title bar.

You have to provide a custom template (probably inherit Window class) to put these buttons up there.