wpf渲染同步

时间:2014-06-17 08:44:01

标签: c# wpf rendering

我有两个自定义WPF控件(带有自定义渲染逻辑)放在彼此的顶部(透明背景和东西)。在某些时候,我想重新绘制这些控件。我的第一个想法是打电话:

foreach(var control in Controls)
{
    control.InvalidateVisual();
}

但这并没有奏效。我的意思是它确实强制渲染我的控件,但是视觉更新不会同时发生。控件逐个更新,这看起来不太好并且可能导致混淆(在一个控件显示更新的视觉,而另一个仍显示旧视觉的情况下)。关于InvalidateVisual方法的文档真的很差,但我想这是一种异步方法,这就是我遇到这个问题的原因。

所以问题是:有没有办法同步多个控件的渲染?除了创建一个包含所有渲染逻辑的mega控件(我想避免这种情况)。

3 个答案:

答案 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