WPF渲染同步
本文关键字:同步 WPF | 更新日期: 2023-09-27 18:08:51
我有两个自定义WPF控件(带有自定义渲染逻辑)放在彼此的顶部(透明背景和东西)。在某些时候,我想重新绘制这些控件。我的第一个想法是调用:
foreach(var control in Controls)
{
control.InvalidateVisual();
}
但这并不完全有效。我的意思是,它确实会强制渲染我的控件,但视觉更新不会同时发生。控件一个接一个地更新,这看起来不太好,可能会导致混淆(在一个控件显示更新的视觉效果,而另一个控件仍然显示旧的视觉效果的情况下)。关于InvalidateVisual
方法的文档真的很差,但我猜这是一个异步方法,这就是为什么我有这个问题。
所以问题是:是否有一种方法来同步呈现多个控件?除了创建一个包含所有渲染逻辑的大型控件(我想避免这种情况)。
一般不应该使用InvalidateVisual()
。
要更新保持相同大小的控件,您可以创建DrawingGroup
并在OnRender()
期间将其放入可视化树中-然后您可以随时使用DrawingGroup.Open()
更新绘图组,WPF将更新UI。
对于您的情况,它看起来像:
class Control1 : UIElement {
DrawingGroup backingStore = new DrawingGroup();
protected override void OnRender(DrawingContext drawingContext) {
base.OnRender(drawingContext);
Render(); // put content into our backingStore
drawingContext.DrawDrawing(backingStore);
}
private void Render() {
var drawingContext = backingStore.Open();
Render(drawingContext);
drawingContext.Close();
}
private void Render(DrawingContext) {
// put your existing drawing commands here.
}
}
class Control2 : UIElement {
DrawingGroup backingStore = new DrawingGroup();
protected override void OnRender(DrawingContext drawingContext) {
base.OnRender(drawingContext);
Render(); // put content into our backingStore
drawingContext.DrawDrawing(backingStore);
}
private void Render() {
var drawingContext = backingStore.Open();
Render(drawingContext);
drawingContext.Close();
}
private void Render(DrawingContext) {
// put your existing drawing commands here.
}
}
class SomeOtherClass {
public void SomeOtherMethod() {
control1.Render();
control2.Render();
}
}
您需要暂停刷新控制,直到您完成所有它们的无效,一种方法如下:
class DrawingControl
{
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, Int32 wMsg, bool wParam, Int32 lParam);
private const int WM_SETREDRAW = 11;
public static void SuspendDrawing( Control parent )
{
SendMessage(parent.Handle, WM_SETREDRAW, false, 0);
}
public static void ResumeDrawing( Control parent )
{
SendMessage(parent.Handle, WM_SETREDRAW, true, 0);
parent.Refresh();
}
}
如何暂停控件及其子控件的绘制? 另一种方法是使用数据绑定来触发渲染,如果控件有一些绑定到视图模型的Data
属性。
public static readonly DependencyProperty DataProperty
= DependencyProperty.Register("Data", typeof(DataType), typeof(MyView),
new FrameworkPropertyMetadata(default(DataType),
FrameworkPropertyMetadataOptions.AffectsRender));
public DataType Data
{
get { return (DataType)GetValue(DataProperty); }
set { SetValue(DataProperty, value); }
}
注意AffectsRender
标志。然后,您可以通过同时更新绑定属性来同时重新绘制所有控件:
foreach(var viewModel in ViewModels)
{
viewModel.Data = ...;
}