简体   繁体   English

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

[英]Force WPF Immediate UI update from UI thread

(Note: Every question I can find related to this "Forcing WPF UI updates" seems to be about triggering one from a background thread . That's not what I want; All my code is in the UI thread .) (注意:我能找到的与“强制 WPF UI 更新”相关的每个问题似乎都是关于从后台线程触发一个问题。这不是我想要的;我所有的代码都在UI 线程中。)

My view-model command-handler changes a public, boolean Failed property bound to a TextBlock 's Visibility .我的视图模型命令处理程序更改了绑定到TextBlockVisibility的公共布尔Failed属性。 This makes the bound TextBlock become visible.这使得绑定的TextBlock变得可见。 This part is all standard, WPF stuff and works fine;这部分都是标准的,WPF的东西并且工作正常; My UI changes and the label appears.我的 UI 发生了变化,标签出现了。

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

But I added code so save a screen-shot of the application window immediately after setting this property.但是我添加了代码,因此在设置此属性后立即保存应用程序窗口的屏幕截图。 The code produces a perfect image of the screen.该代码会生成完美的屏幕图像。 Unfortunately it is of the screen as it was before I changed the property because WPF has not yet had a chance to render the changes.不幸的是,它与我更改属性之前的屏幕一样,因为 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);

Is there a way to force WPF to force it to process all property changes, do layout and rendering before I continue?有没有办法强制 WPF 强制它处理所有属性更改,在我继续之前进行布局和渲染? Or maybe some type of "update complete" event I could hook up to?或者也许我可以连接某种类型的“更新完成”事件?

Currently I'm using a hack that looks bad even to me: I made the command handler async and preceded my writing code with this, using an arbitrary background delay before the continuing on to write目前我正在使用一个对我来说看起来很糟糕的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);

But this doesn't seem to me to be a very robust way to do this.但在我看来,这似乎不是一个非常可靠的方法。 Is there something better?有更好的吗?

Before taking screenshot call this GridParent.UpdateLayout();在截屏之前调用这个GridParent.UpdateLayout(); here GridParent can be parent control or like you are doing Application.Current.MainWindow.UpdateLayout();这里GridParent可以是父控件或者像你在做Application.Current.MainWindow.UpdateLayout(); . .

I've tried it.我试过了。 it will make sure UI is rendered before taking screenshot.它将确保在截屏之前呈现 UI。

Also, i used this method to take screenshot.另外,我用这种方法截屏。

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);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM