wpf 窗口淡入导致窗口内容在淡入之前快速 Flink 白色

oogrdqng  于 2023-01-02  发布在  Flink
关注(0)|答案(3)|浏览(171)

我希望WPF窗口在打开时淡入。我设置了以下窗口加载触发器:

<Window.Triggers>
    <EventTrigger RoutedEvent="Window.Loaded">
        <BeginStoryboard>
            <Storyboard Name="FormFade">
                <DoubleAnimation  Name="FormFadeAnimation"
                                        Storyboard.TargetName="Window"
                                        Storyboard.TargetProperty="(Window.Opacity)"
                                        From="0.0" To="1.0" Duration="0:0:5"
                                        AutoReverse="False" RepeatBehavior="1x"
                                     />
            </Storyboard>
        </BeginStoryboard>
    </EventTrigger>
</Window.Triggers>

问题是,当窗口第一次加载时,它显示所有白色的内容,然后消失,然后窗口内容淡入如预期。我如何才能摆脱白色 Flink 发生在开始?我甚至设置了窗口的背景为黑色,但它仍然 Flink 白色。

8xiog9wr

8xiog9wr1#

我认为问题是由Window.loaded处理程序中的处理引起的。在Window.loaded处理程序完成执行之前,动画不会运行。我可以通过以下操作重新创建问题:

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
        }

        void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            Thread.Sleep(1000);
        }
    }
}

屏幕将为白色1000毫秒,因为动画将不会运行,直到睡眠结束。如果你拿走Thread.Sleep()调用,结果是你所期望的。我猜你正在做相当多的工作,在你的加载处理程序和动画被延迟。
顺便说一下,这里是MainWindow.xaml,几乎与您所拥有的相同:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" x:Name="Window">
    <Window.Triggers>
        <EventTrigger RoutedEvent="Window.Loaded">
            <BeginStoryboard>
                <Storyboard Name="FormFade">
                    <DoubleAnimation  Name="FormFadeAnimation"
                                        Storyboard.TargetName="Window"
                                        Storyboard.TargetProperty="(Window.Opacity)"
                                        From="0.0" To="1.0" Duration="0:0:5"
                                        AutoReverse="False" RepeatBehavior="1x"
                                     />
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Window.Triggers>
    <Grid>
        <TextBlock>asdf</TextBlock>
    </Grid>
</Window>
qnakjoqk

qnakjoqk2#

尝试在<Window>标记中将Window.Opacity设置为开始。
编辑:@H.B是绝对正确的。窗口也需要有AllowsTransparency=true,为此,窗口chrome需要关闭(WindowStyle=None)。我重现了你的问题,然后这样做,使它按照你想要的方式工作:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" 
        Opacity="0" AllowsTransparency="True" WindowStyle="None">
    <Window.Triggers>
        <EventTrigger RoutedEvent="Window.Loaded">
            <BeginStoryboard>
                <Storyboard Name="FormFade">
                    <DoubleAnimation  Name="FormFadeAnimation"
                                        Storyboard.TargetProperty="(Window.Opacity)"
                                        From="0.0" To="1.0" Duration="0:0:5"
                                        AutoReverse="False" RepeatBehavior="1x"
                                     />
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Window.Triggers>
    <Grid>

    </Grid>
</Window>
iswrvxsc

iswrvxsc3#

问题

我也遇到过这种情况。提供的答案没有帮助,因为我想"重新显示"同一个窗口。如果你在窗口上调用.Hide(),然后调用.Show(),第一帧将是完全不透明的。
溶液
我最好的猜测是窗口在.Show()上重新呈现,但是它最后一次显示。我可能是错的。但是修复起作用了。本质上我们需要确保我们在Hide()之前正确地设置Opacity=0
使用代码隐藏,因为xaml故事板的排列对我来说都不起作用。如果我错了请纠正我。
创建一个扩展方法以保持美观:

public static class Animate
{
    public static void fade_in(this Window window)
    {
        fade(window, () => { });
    }

    public static void fade_out(this Window window, Action on_finish)
    {
        fade(window, on_finish, start:1, end:0);
    }

    static void fade(this Window window, Action on_finish, double duration_in_seconds = 0.15, double start = 0, double end = 1)
    {
        // This will all be optimized by the compiler.
        int frames_per_second = 60;  // Give us a smooth animation
        double change = end - start;
        double change_per_second = change / duration_in_seconds;
        double change_per_frame = change_per_second / frames_per_second;
        double number_of_frames = duration_in_seconds * frames_per_second;

        Task t = Task.Run(() =>
        {
            for (int i = 0; i < number_of_frames; i++)
            {
                var proportion_complete = (i+1) / number_of_frames;
                window.Dispatcher.Invoke(() => { window.Opacity = Lerp(start, end, proportion_complete); });

                Thread.Sleep(1000 / 60);  // Sleep 1/60'th of a second.  Likely the monitor's refresh rate.
            }

            on_finish();
        });
    }

    static double Lerp(double first, double second, double by)
    {
        return first + (second - first) * by;
    }
}

然后,当您想要隐藏您的弹出窗口:

popup_window.fade_out(() => popup_window.Dispatcher.Invoke(popup_window.Hide));

然后用这个来表示:

popup_window.fade_in();
popup_window.Show();

希望这有帮助!

陷阱

如果你的窗口像@Chris Shain建议的那样开始透明,你可能想在XAML中设置Opacity = 0。
此外,保持动画速度相当快,这样就不必担心淡入/淡出动画重叠。

相关问题