C# 多次显示和隐藏带有幻灯片动画的WPF窗口,同时每次都一致地显示动画

C# 多次显示和隐藏带有幻灯片动画的WPF窗口,同时每次都一致地显示动画,c#,wpf,xaml,C#,Wpf,Xaml,我想在屏幕右下角显示WPF幻灯片通知。我需要在主程序中多次显示和隐藏通知,因此无法每次关闭()和显示()窗口。我必须继续做Hide()和Show() IshittesVisible设置为False,这样我就可以单击窗口上的任意位置来取消和隐藏通知,并将另一个窗口置于前台 我第一次执行窗口动画时,它运行得非常完美。如果我让窗口动画一直运行到最后,那么下次显示幻灯片通知时,动画将完美显示 如果在动画运行完整个过程之前单击窗口,问题就会出现。单击窗口将隐藏窗口,然后将情节提要设置为SkipStoryb

我想在屏幕右下角显示WPF幻灯片通知。我需要在主程序中多次显示和隐藏通知,因此无法每次关闭()和显示()窗口。我必须继续做Hide()和Show()

IshittesVisible设置为False,这样我就可以单击窗口上的任意位置来取消和隐藏通知,并将另一个窗口置于前台

我第一次执行窗口动画时,它运行得非常完美。如果我让窗口动画一直运行到最后,那么下次显示幻灯片通知时,动画将完美显示

如果在动画运行完整个过程之前单击窗口,问题就会出现。单击窗口将隐藏窗口,然后将情节提要设置为SkipStoryboardtoFill,并将FillBehavior设置为Stop,以便动画时钟重置为其原始值。但是,下次显示隐藏的通知窗口时,它似乎会记住窗口隐藏之前的最后一个窗口位置,然后启动动画。所以动画看起来很奇怪。我试图找出如何设置动画,使其每次都以相同的方式显示,而不会出现此问题

<Window
x:Class="NotificationWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Notification Popup"
Width="480"
Height="140"
WindowStyle="None"
AllowsTransparency="True"
Background="Transparent"
>

<Grid Name="ToastWindowGrid" RenderTransformOrigin="0,1">

    <Border Name="ToastWindowBorder" BorderThickness="0" Background="#333333">

        <StackPanel Name="ToastWindowStackPanel" Margin="10" Orientation="Horizontal">

            <Image Name="ToastLogo" Width="100" Height="100" Source="D:\Development\resources\WindowsLogo-Blue-x100.png"/>

            <StackPanel Name="ToastMessageStackPanel" Width="359">

                <TextBox Name="ToastTitleTextBox" Margin="5" MaxWidth="340" Background="#333333" BorderThickness="0" IsReadOnly="True" Foreground="White" FontSize="20" Text="Windows 10 Upgrade" FontWeight="Bold" HorizontalContentAlignment="Center" Width="Auto" HorizontalAlignment="Stretch" IsHitTestVisible="False"/>

                <TextBox Name="TotastMessageTextBox" Margin="5" MaxWidth="340" Background="#333333" BorderThickness="0" IsReadOnly="True" Foreground="LightGray" FontSize="16" Text="A Windows upgrade is available. Click to upgrade or schedule update." HorizontalContentAlignment="Left" TextWrapping="Wrap" IsHitTestVisible="False"/>

            </StackPanel>

        </StackPanel>

    </Border>

    <Grid.Triggers>

        <EventTrigger RoutedEvent="FrameworkElement.Loaded">
            <BeginStoryboard Name="BeginToastAnimationStoryboard">
                <Storyboard Name="ToastAnimationStoryboard" FillBehavior="Stop">
                    <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)" FillBehavior="Stop">
                        <SplineDoubleKeyFrame KeyTime="0:0:0" Value="0"/>
                        <SplineDoubleKeyFrame KeyTime="0:0:0.5" Value="1"/>
                    </DoubleAnimationUsingKeyFrames>
                    <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" FillBehavior="Stop">
                        <SplineDoubleKeyFrame KeyTime="0:0:18" Value="1"/>
                        <SplineDoubleKeyFrame KeyTime="0:0:20" Value="0"/>
                    </DoubleAnimationUsingKeyFrames>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>

        <EventTrigger RoutedEvent="FrameworkElement.MouseUp">
            <SkipStoryboardToFill BeginStoryboardName="BeginToastAnimationStoryboard"/>
            <RemoveStoryboard BeginStoryboardName="BeginToastAnimationStoryboard"/>
        </EventTrigger>

    </Grid.Triggers>

    <Grid.RenderTransform>
        <ScaleTransform ScaleY="1" />
    </Grid.RenderTransform>

</Grid>

第一次显示通知时,我使用加载的事件处理程序调用Begin方法,并将iscontrolable设置为True。之后,如果窗口的Visibility属性设置为Visible,我将使用IsVisibleChanged事件处理程序启动动画。

我建议为每个通知创建一个新实例。让我解释一下原因

  • 您可以使用配置对象独立地配置它们,例如,一个对象可以保持可见10秒,而其余通知则默认为5秒
  • 您可以一次显示多个通知
  • 作为窗口的每个通知都将启动自己的事件循环和线程

  • 但是,要使其工作,您必须确保窗口非常轻并且可以非常快地初始化。

    将MouseUp EventTrigger更改为:

  • 使用SeekStoryboard重置为动画的开头
  • 使用PauseStoryboard停止动画。使用StopStoryboard将动画运行到填充状态,这不是您想要的:您希望窗口消失
  • 以下是xaml中的更改:

            <EventTrigger RoutedEvent="FrameworkElement.MouseUp">
                <SeekStoryboard BeginStoryboardName="BeginToastAnimationStoryboard" />
                <PauseStoryboard BeginStoryboardName="BeginToastAnimationStoryboard" />
            </EventTrigger>
    
    
    

    重置动画可确保重新启动动画时,动画将从情节提要的开头重新开始。

    是的,如果我不明白为什么单击窗口将其关闭,然后将其隐藏,然后再次显示会导致动画:从其终点开始,然后向下闪到起点,然后返回到终点。如果我只是让窗口通过淡入淡出而不单击它,那么下次显示窗口时动画将正确启动。我觉得我错过了一些非常简单的东西。当显示窗口时,首先想到的是重置故事板。
            <EventTrigger RoutedEvent="FrameworkElement.MouseUp">
                <SeekStoryboard BeginStoryboardName="BeginToastAnimationStoryboard" />
                <PauseStoryboard BeginStoryboardName="BeginToastAnimationStoryboard" />
            </EventTrigger>