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

k4ymrczo  于 2023-08-07  发布在  其他
关注(0)|答案(2)|浏览(104)

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

<Grid>
    <Grid>
        <!-- STUFF -->
    </Grid>
    <Rectangle Fill="White" Opacity="0.7" Visibility="{Binding VisibilityWait, Mode=TwoWay, 
    Converter={StaticResource BoolToVisibilityConverter}}" />
</Grid>

字符串
MyViewModel然后实现INotifyPropertyChanged并包含属性;

private bool visibilityWait;
    public bool VisibilityWait
    {
        get
        {
            return visibilityWait;
        }
        set
        {
            visibilityWait = value;
            OnPropertyChanged("VisibilityWait");
        }
    }


我知道这是正确设置的,因为如果我在构造函数中将VisibilityWait设置为true,窗口将显示预期的“Loading”覆盖,反之亦然......但是,如果我尝试在一个方法期间这样做,例如;

private void someMethod()
{
    VisibilityWait = true;
    //... Do things
    VisibilityWait = false;
}


然后,在程序处于“做事情”部分期间,UI不会更新以显示加载覆盖。
如何解决此问题?
编辑:我找到了自己解决这个问题的方法。请看下面的答案。

rqqzpn5f

rqqzpn5f1#

通常,当一个函数正在发生时,对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 { }));
    }

字符串
编辑:我在AllowUIToUpdate函数中添加了额外的一行,现在一切都如预期的那样运行了!

ttisahbt

ttisahbt2#

对@刘易斯_Heslop答案的改进,它可以完美地与MVVM一起工作:

private static void AllowUIToUpdate()
{
    DispatcherFrame frame = new();
    // DispatcherPriority set to Input, the highest priority
    Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Input, new DispatcherOperationCallback(delegate (object parameter)
    {
        frame.Continue = false;
        Thread.Sleep(20); // Stop all processes to make sure the UI update is perform
        return null;
    }), null);
    Dispatcher.PushFrame(frame);
    // DispatcherPriority set to Input, the highest priority
    Application.Current.Dispatcher.Invoke(DispatcherPriority.Input, new Action(delegate { }));
}

字符串

相关问题