我有两个自定义WPF控件(带有自定义渲染逻辑)放在彼此的顶部(透明背景和东西)。在某些时候,我想重新绘制这些控件。我的第一个想法是打电话:
foreach(var control in Controls)
{
control.InvalidateVisual();
}
但这并没有奏效。我的意思是它确实强制渲染我的控件,但是视觉更新不会同时发生。控件逐个更新,这看起来不太好并且可能导致混淆(在一个控件显示更新的视觉,而另一个仍显示旧视觉的情况下)。关于InvalidateVisual
方法的文档真的很差,但我想这是一种异步方法,这就是我遇到这个问题的原因。
所以问题是:有没有办法同步多个控件的渲染?除了创建一个包含所有渲染逻辑的mega控件(我想避免这种情况)。
答案 0 :(得分:1)
你需要暂停刷新控制,直到你完成所有这些操作的无效,其中一种方式如下:
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();
}
}
请点击此处查看其他方式:How do I suspend painting for a control and its children?
答案 1 :(得分:1)
您通常不应使用InvalidateVisual()
。
要更新保持相同大小的控件,您可以创建DrawingGroup
并在OnRender()
期间将其放入可视树中 - 然后您可以随时更新绘图组DrawingGroup.Open()
,WPF将更新用户界面。
对于您的情况,这看起来像:
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();
}
}
答案 2 :(得分:0)
另一种方法是使用数据绑定来触发渲染,如果控件具有绑定到viewmodel的某个@font-face
font-family: 'ProximaNovaCnBold'
src: url('/proxima_nova_bold-webfont.eot') format('eot')
属性。
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