如何在 UI 线程的冗长任务期间强制 UI 更新

Lew*_*lop 2 wpf user-interface mvvm

我有一个窗口,该窗口包含它的内容和“正在加载”覆盖,如下所示

<Grid>
    <Grid>
        <!-- STUFF -->
    </Grid>
    <Rectangle Fill="White" Opacity="0.7" Visibility="{Binding VisibilityWait, Mode=TwoWay, 
    Converter={StaticResource BoolToVisibilityConverter}}" />
</Grid>
Run Code Online (Sandbox Code Playgroud)

我的 ViewModel 然后实现 INotifyPropertyChanged 并包含该属性;

    private bool visibilityWait;
    public bool VisibilityWait
    {
        get
        {
            return visibilityWait;
        }
        set
        {
            visibilityWait = value;
            OnPropertyChanged("VisibilityWait");
        }
    }
Run Code Online (Sandbox Code Playgroud)

我知道这是正确设置的,因为如果我在构造函数中将 VisibilityWait 设置为 true,则窗口会按预期显示“正在加载”覆盖,反之亦然......但是,如果我尝试在方法中执行此操作,例如;

private void someMethod()
{
    VisibilityWait = true;
    //... Do things
    VisibilityWait = false;
}
Run Code Online (Sandbox Code Playgroud)

然后在程序处于“执行操作”部分期间,UI 不会更新以显示加载覆盖。

我该如何解决这个问题?

编辑:我找到了我自己的解决方案。请参阅下面的答案。

Lew*_*lop 7

通常当一个函数发生时,对 UI 的任何更新都会被阻止,直到函数结束。这是因为直到函数结束时帧才会被推送。您可以通过调用这样的方法来强制进行此更新;

    void AllowUIToUpdate()
    {
        DispatcherFrame frame = new DispatcherFrame();
        Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Render, new DispatcherOperationCallback(delegate (object parameter)
        {
            frame.Continue = false;
            return null;
        }), null);

        Dispatcher.PushFrame(frame);
        //EDIT:
        Application.Current.Dispatcher.Invoke(DispatcherPriority.Background,
                                      new Action(delegate { }));
    }
Run Code Online (Sandbox Code Playgroud)

编辑:我在 AllowUIToUpdate 函数中添加了额外的一行,现在一切都按预期运行了!