我想劫持通常的 WPF 渲染以将控件拆分为基元,进行布局管理,为我应用绑定(bind)等。
据我所知,WPF 中的整个渲染归结为在布局管理器计算的位置使用依赖属性系统定义的值渲染图元(文本、图像、直线、曲线)。如果我可以提供我自己的原始渲染逻辑,我将能够渲染例如到自定义文档类型,传输原语以通过网络等进行真实渲染。
我的计划如下:
- 实现自定义
DrawingContext
.DrawingContext
是一个抽象类,它定义了一堆方法,如DrawEllipse
、DrawText
、DrawImage
等 —我需要为此功能提供我自己的实现。 - 创建一个 WPF
UserControl
并强制它呈现给给定的DrawingContext
。
但是我遇到了以下问题:
DrawingContext
包含抽象内部方法void PushGuidelineY1(double coordinate)
和void PushGuidelineY2(double leadingCoordinate, double offsetToDrivenCoordinate)
,我无法覆盖容易地。 (也许有一些技巧可以克服这个问题?)- 似乎没有方法可以在
DrawingContext
上呈现整个 视觉效果?为什么?
我可以做类似的事情
void RenderRecursively(UIElement e, DrawingContext ctx)
{
e.OnRender(ctx);
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(e); i++)
RenderRecursively((UIElement)VisualTreeHelper.GetChild(e, i), ctx);
}
— 但我想知道是否有直接的方法来呈现 UIElement
。 (当然,这个问题是一个小问题,但看到没有基础设施让我怀疑这是否是正确的方法。)
那么,DrawingContext
不是用来继承的吗?提供自定义 DrawingContext
的整个想法是朝着正确方向迈出的一步,还是我需要重新考虑该策略?是在 WPF 支持的自定义上下文中绘图,还是我需要寻找不同的拦截点?
最佳答案
您可能需要从相反的方向来解决这个问题。您可以要求 WPF 为您提供 Drawing
,而不是旨在提供您自己的 DrawingContext
。所以它更像是一种“拉动”方法,而不是你想要的“推”方法,但它应该可以到达同一个地方:如果你有一个 Drawing
可视化树部分外观的完整表示,这是一个数据结构,您可以遍历并发现通过调用自定义 DrawingContext
可以发现的所有内容。
我相信这与塞巴斯蒂安提到的 XPS 文档导出在内部使用的基本方法相同。但是,与通过 XPS API 使用它相比,自己直接使用它是一种更直接的方法
核心是相当简单的:VisualTreeHelper.GetDrawing
.这将返回一个 DrawingGroup
。 (Drawing
是一个抽象基类。)该文档页面向您展示了如何遍历返回的树。不幸的是,这并没有完成全部工作:它只是为您碰巧调用它的任何节点提供视觉效果,如果该节点有子节点,则不会包括它们。
因此,不幸的是,您仍然需要编写一些递归可视化树的内容,就像您已经计划的那样。您还需要处理附加到视觉对象的任何不透明蒙版、非基于蒙版的不透明度、剪辑区域、效果和转换以获得正确的结果;您也必须做所有这些才能使您提出的方法正常工作,所以这里没有什么真正的改变。 (如 Sebastian 所建议的那样,使用 XPS API 的一个潜在优势是它会为您完成所有这些工作。但是,以您想要的形式从 XPS 文档中提取信息就是您的问题了,这可能最终会丢失您想要的信息可能想要保留。)
关于c# - 呈现到自定义 DrawingContext,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18193122/