从 UI 线程强制 WPF 立即 UI 更新

Force WPF Immediate UI update from UI thread

(注意:我能找到的每个与“强制 WPF UI 更新”相关的问题似乎都是关于从 后台线程 触发一个。那不是什么我想要;我所有的代码都在 UI thread.)

我的视图模型命令处理程序更改 public、布尔值 Failed 属性 绑定到 TextBlockVisibility。这使得绑定 TextBlock 变得可见。这部分都是标准的,WPF 的东西并且工作正常;我的 UI 发生变化并出现标签。

<TextBlock Text="Failed" Visibility="{Binding Failed, Converter="{StaticResource CvtBoolToVisibility}}" Foreground="Red" />

但我添加了代码,因此在设置 属性 后立即保存应用程序的屏幕截图 window。该代码生成完美的屏幕图像。不幸的是它在屏幕上是 before 我更改了 属性 因为 WPF 还没有机会呈现更改。

var window    = Application.Current.MainWindow ?? throw new InvalidOperationException("No window");
var bm        = window.CopyAsBitmap()          ?? throw new InvalidOperationException("Unable to copy bitmap");
var pngData   = bm.Encode(new PngBitmapEncoder());
File.WriteAllBytes(Path.Combine(SaveFolder, "TestOutput.png"), pngData);

有没有办法强制 WPF 强制它处理所有 属性 更改,在我继续之前进行布局和渲染?或者我可以连接到某种类型的“更新完成”事件?

目前我正在使用一个甚至对我来说也很糟糕的 hack:我使命令处理程序异步并在我编写代码之前使用它,在继续编写之前使用任意背景延迟

await Task.Delay(500).ConfigureAwait(true);  // Give WPF a chance to update.

var window    = Application.Current.MainWindow ?? throw new InvalidOperationException("No window");
var bm        = window.CopyAsBitmap()          ?? throw new InvalidOperationException("Unable to copy bitmap");
var pngData   = bm.Encode(new PngBitmapEncoder());
await File.WriteAllBytesAsync(Path.Combine(SaveFolder, "TestOutput.png"), pngData);

但在我看来,这并不是一种非常有效的方法。还有更好的吗?

在截取屏幕截图之前调用此 GridParent.UpdateLayout(); 此处 GridParent 可以是父控件或像你正在做的那样 Application.Current.MainWindow.UpdateLayout();

我试过了。它将确保 UI 在截屏之前呈现。

另外,我也是用这个方法截屏的

private void SaveSnap()
{
    RenderTargetBitmap renderTargetBitmap =
        new RenderTargetBitmap((int) GridParent.ActualWidth, (int) GridParent.ActualHeight, 96, 96,
            PixelFormats.Pbgra32);
    renderTargetBitmap.Render(GridParent);
    PngBitmapEncoder pngImage = new PngBitmapEncoder();
    pngImage.Frames.Add(BitmapFrame.Create(renderTargetBitmap));
    using (Stream fileStream = File.Create("Img.png"))
    {
        pngImage.Save(fileStream);
    }
}