DrawingVisual的懒惰渲染

时间:2014-05-26 02:20:43

标签: c# wpf drawingvisual

我尝试更改自定义WPF元素以使用可视树,以便可以更改背景图层而无需丢弃整个保留的渲染。同时,一个图层可能会受到多个属性的影响,因此我想懒得重做渲染,以防在单个屏幕更新周期中更改多个属性。这就是我的所作所为。

protected override int VisualChildrenCount
{
    get
    {
        return 1;
    }
}

private readonly DrawingVisual textLayer = new DrawingVisual();
bool textLayerReady;
protected override Visual GetVisualChild(int index)
{
    switch (index)
    {
        case 0:
            if (!textLayerReady)
            {
                using (var textContext = textLayer.RenderOpen())
                    RenderTextLayer(textContext);
            }
            return textLayer;
        default:
            throw new ArgumentOutOfRangeException("index");
    }
}

它似乎运行正常,但在设计师我得到:

  

InvalidOperationException:在OnRender回调期间无法调用此API。在OnRender期间,只能执行绘制Visual内容的绘制操作。

我想在运行时布局过程在实际渲染之前调用GetVisualChild,而设计画布的运行方式不同?

尝试这是合理的吗?我应该如何触发儿童绘画视觉的渲染,以确保它在法定时间发生?

2 个答案:

答案 0 :(得分:0)

您可以通过相应地检测它来阻止在设计时进行渲染

所以,如果我稍微修改你的代码,那么它在设计师中应该表现得很好

private readonly DrawingVisual textLayer = new DrawingVisual();
bool textLayerReady;
protected override Visual GetVisualChild(int index)
{
    if (System.ComponentModel.DesignerProperties.GetIsInDesignMode(this)) 
    {
        return; //do not perform custom logic during design time
    }

    switch (index)
    {
        case 0:
            if (!textLayerReady)
            {
                using (var textContext = textLayer.RenderOpen())
                    RenderTextLayer(textContext);
            }
            return textLayer;
        default:
            throw new ArgumentOutOfRangeException("index");
    }
}

答案 1 :(得分:0)

如果在渲染周期中修改了Visuals本身会抛出异常,设计人员会在渲染周期中获取视觉效果,而无需事先通过排列处理。

但是,即使DrawingGroupDrawingGroup的成员,在呈现期间修改Visual的内容也是完全合法的。

只需在构造函数中将DrawingGroup添加到DrawingVisual一次:

DrawingGroup textLayer = new DrawingGroup();
DrawingVisual textVisual = new DrawingVisual();
using (DrawingContext textContext = textVisual.RenderOpen())
    textContext.DrawDrawing(textLayer);

然后,人们可以在实际需要渲染时懒惰地替换内容,同时仍然保留保留模式的优点(不重建"矢量图形指令列表"作为WPF术语吧,对于未更改的图层)。

protected override Visual GetVisualChild(int index)
{
    switch (index)
    {
        case 0:
            if (!textLayerReady)
            {
                using (var textContext = textLayer.Open())
                    RenderTextLayer(textContext);
            }
            return textVisual;

        default:
            throw new ArgumentOutOfRangeException("index");
    }
}
相关问题