关闭时淡出wpf窗口

Jam*_*mes 22 c# wpf animation routedevent eventtrigger

我想在我的应用程序中淡入/淡出一个窗口.
淡入时发生Window.Loaded,我想在关闭(Window.ClosedWindow.Closing)时淡出.淡入效果完美,但Window.Closing不允许RoutedEvent财产价值.
RoutedEvent应该用什么关闭?

    <Window.Triggers>
        <EventTrigger RoutedEvent="Window.Loaded">
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimation Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:2" FillBehavior="HoldEnd" />
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
        <EventTrigger RoutedEvent="Window.Closing">
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimation Storyboard.TargetProperty="Opacity" From="1" To="0" Duration="0:0:2" FillBehavior="HoldEnd" />
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Window.Triggers>
Run Code Online (Sandbox Code Playgroud)

我收到错误,值'Window.Closing'无法分配给属性'RoutedEvent'.无效的活动名称.

Tho*_*que 32

Closing不是路由事件,因此您无法在EventTrigger中使用它.也许你可以在代码隐藏中的ClosingEvent的处理程序中启动故事板并取消事件...类似的东西:

private bool closeStoryBoardCompleted = false;

private void Window_Closing(object sender, CancelEventArgs e)
{
    if (!closeStoryBoardCompleted)
    {
        closeStoryBoard.Begin();
        e.Cancel = true;
    }
}

private void closeStoryBoard_Completed(object sender, EventArgs e)
{
    closeStoryBoardCompleted = true;
    this.Close();
}
Run Code Online (Sandbox Code Playgroud)

  • 别忘了将<Storyboard Completed ="closeStoryBoard_Completed">添加到结束故事板. (5认同)
  • 如果你得到一个错误,说故事板需要一个目标,将 `this` 传递给 `closeStoryBoard.Begin();`。 (2认同)

Pat*_*ick 8

我想我会添加另一种解决方案,使用Expression SDK中的行为并将其与@Thomas的解决方案相结合.使用它,我们可以定义一个"CloseBehavior"来处理启动故事板并在完成后关闭窗口的代码.

using System.ComponentModel;
using System.Windows;
using System.Windows.Interactivity;
using System.Windows.Media.Animation;

namespace Presentation.Behaviours {
    public class CloseBehavior : Behavior<Window> {
        public static readonly DependencyProperty StoryboardProperty =
            DependencyProperty.Register("Storyboard", typeof(Storyboard), typeof(CloseBehavior), new PropertyMetadata(default(Storyboard)));

        public Storyboard Storyboard {
            get { return (Storyboard)GetValue(StoryboardProperty); }
            set { SetValue(StoryboardProperty, value); }
        }

        protected override void OnAttached() {
            base.OnAttached();
            AssociatedObject.Closing += onWindowClosing;
        }

        private void onWindowClosing(object sender, CancelEventArgs e) {
            if (Storyboard == null) {
                return;
            }
            e.Cancel = true;
            AssociatedObject.Closing -= onWindowClosing;

            Storyboard.Completed += (o, a) => AssociatedObject.Close();
            Storyboard.Begin(AssociatedObject);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

该行为将故事板定义为依赖属性,因此我们可以在xaml中设置它,并且当AssociatedObject(我们定义行为的窗口)关闭时,此故事板将使用Storyboard.Begin().现在,在xaml中,我们只需使用以下xaml将行为添加到窗口中

<Window x:Class="Presentation.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:behave="clr-namespace:Presentation.Behaviours"
        xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
        x:Name="window">
    <Window.Resources>
        <Storyboard x:Key="ExitAnimation">
            <DoubleAnimation Storyboard.Target="{Binding ElementName='window'}"
                             Storyboard.TargetProperty="(Window.Opacity)"
                             Duration="0:0:1" From="1" To="0"/>
        </Storyboard>
    </Window.Resources>

    <i:Interaction.Behaviors>
        <behave:CloseBehavior Storyboard="{StaticResource ExitAnimation}"/>
    </i:Interaction.Behaviors>

    <Grid>
    </Grid>
</Window>
Run Code Online (Sandbox Code Playgroud)

请注意iSystem.Windows.Interactivity dll中的xml命名空间,并且还引用了窗口,因此必须x:Name分配该窗口.现在,我们只需将行为添加到我们希望在关闭应用程序之前执行故事板的每个窗口,而不是将逻辑复制到每个窗口中的每个代码隐藏.

  • 非常好,工作正常,没有背后的代码 - 这是更好的答案 (2认同)