22

我想在我的应用程序中淡入/淡出一个窗口。
淡入发生在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>

我收到错误消息,无法将值“Window.Closing”分配给属性“RoutedEvent”。事件名称无效。

4

5 回答 5

32

关闭不是路由事件,因此您不能在 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();
}
于 2009-05-15T12:04:02.100 回答
9

我想我会添加另一个解决方案,使用 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);
        }
    }
}

该行为将故事板定义为依赖属性,因此我们可以在 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>

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

于 2012-09-17T15:23:00.023 回答
1

我不是 WPF 方面的专家,但我相信除非你取消最初的 Closing 事件,否则窗口甚至会在动画开始之前消失。

收到 Window.Closing 事件后,您应该取消该事件并启动动画。动画完成后,您可以关闭窗口。

于 2009-05-15T11:50:16.453 回答
0

这甚至更简单、更短。添加如下行为:

public class WindowClosingBehavior : Behavior<Window>
    {
        protected override void OnAttached()
        {
            AssociatedObject.Closing += AssociatedObject_Closing;
        }

        private void AssociatedObject_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            Window window = sender as Window;
            window.Closing -= AssociatedObject_Closing;
            e.Cancel = true;
            var anim = new DoubleAnimation(0, (Duration)TimeSpan.FromSeconds(0.5));
            anim.Completed += (s, _) => window.Close();
            window.BeginAnimation(UIElement.OpacityProperty, anim);
        }
        protected override void OnDetaching()
        {
            AssociatedObject.Closing -= AssociatedObject_Closing;
        }
    }

然后在您的窗口中添加参考:

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:wt="clr-namespace:Desktop.Themes.WindowTask;assembly=Desktop.Themes"

插入行为:

<i:Interaction.Behaviors>
     <wt:WindowClosingBehavior />
</i:Interaction.Behaviors>
于 2016-10-19T01:00:57.240 回答
-2

将自动反转设置为“真”

<Window.Triggers>
        <EventTrigger RoutedEvent="Window.Loaded">
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimation Storyboard.TargetProperty="Opacity" AutoReverse="True" From="0" To="1" Duration="0:0:0.5" FillBehavior="HoldEnd" />
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Window.Triggers>
于 2014-09-18T19:01:11.420 回答