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



(注意:我能找到的每个问题都与"强制WPF UI更新"有关)似乎是关于触发一个从背景线程。那不是我想要的;我所有的代码都在UI线程)

我的视图模型命令处理程序更改了绑定到TextBlockVisibility的公共布尔Failed属性。这使得束缚的TextBlock变得可见。这部分是所有标准,WPF材料和工作良好;我的UI改变了,标签出现了。

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

但是我添加了代码,以便在设置此属性后立即保存应用程序窗口的屏幕截图。代码生成一个完美的屏幕图像。不幸的是,在我更改属性之前,它是的屏幕,因为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强制它处理所有属性更改,在我继续之前进行布局和渲染?或者是某种类型的update complete;我能参加的活动?

目前我正在使用一种看起来很糟糕的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);
}
}

最新更新