在 WPF 中,是否有“渲染完成”事件?

cap*_*nst 3 wpf

在 WPF 中,当我加载包含大量元素的环绕面板时,窗口会在显示内容之前暂停一段时间。我想添加一个等待提示,但我找不到检测包装面板何时完成渲染的方法。

我尝试过“加载”、“大小改变”、“初始化”,但都没有成功。有没有人对这个问题有任何想法?

非常感谢 !

Ben*_*ton 12

我知道此时这个问题有点老了,但我刚刚遇到了同样的问题,并找到了一个很好的解决方法,并认为这可以在未来帮助其他人。在渲染开始时调用 Dispatcher.BeginInvoke 和 ContextIdle 的 Dispatcher Priority。我的渲染开始恰好是树视图选定项更改事件,但这可能是您需要等待 UI 完成更新的任何事件。

    private void TreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
    {
        Dispatcher.BeginInvoke(new Action(() => DoSomething()), DispatcherPriority.ContextIdle, null);
    }

    private void DoSomething()
    {
       //This will get called after the UI is complete rendering
    }
Run Code Online (Sandbox Code Playgroud)


Jam*_*urt 7

是的,使用 Window.ContentRendered事件


Wou*_*ter 1

您可以重写 OnRender 方法来检测渲染何时完成。

要推送所有事件,请调用 Dispatcher.DoEvents(),其中 DoEvents 作为扩展方法实现:

public static class DispatcherExtensions
{
    public static void DoEvents(this Dispatcher dispatcher, DispatcherPriority priority = DispatcherPriority.Background)
    {
        DispatcherFrame frame = new DispatcherFrame();
        DispatcherOperation dispatcherOperation = dispatcher.BeginInvoke(priority, (Action<DispatcherFrame>)ExitFrame, frame);
        Dispatcher.PushFrame(frame);

       if (dispatcherOperation.Status != DispatcherOperationStatus.Completed)
           dispatcherOperation.Abort();
   }

    private static void ExitFrame(DispatcherFrame frame)
    {
        frame.Continue = false;
    }

    public static void Flush(this Dispatcher dispatcher, DispatcherPriority priority)
    {
        dispatcher.Invoke(()=> { }, priority);
    }
Run Code Online (Sandbox Code Playgroud)

}

回想起来,我认为使用它是一个糟糕的主意,因为它可能会导致难以解决的错误。

// this shows how bad it is to call Flush or DoEvents
int clicker = 0;
private void OnClick(object sender, RoutedEventArgs e)
{
    if (clicker != 0)
    {
        // This is reachable... // Could be skipped for DispatcherPriority.Render but then again for render it seems to freeze sometimes.
    }
    clicker++;
    Thread.Sleep(100);
    this.Dispatcher.Flush(DispatcherPriority.Input);

    //this.Dispatcher.DoEvents(DispatcherPriority.Render);
    //this.Dispatcher.DoEvents(DispatcherPriority.Loaded);
    //this.Dispatcher.DoEvents(DispatcherPriority.Input);
    //this.Dispatcher.DoEvents(DispatcherPriority.Background);
    clicker--;
}
Run Code Online (Sandbox Code Playgroud)