我正在创建一个严重依赖图节点树的工具。当前的实现是用Java完成的,我将它移植到C#上的通用代码库中,因此它可以被各种渲染实现使用,也因为我想使用WPF的强大功能来实现用户友好的界面。 / p>
浏览了一天之后,我遇到了各种通过WPF绘制矢量图形的方法。
This guy谈论WPF开发人员可以选择的不同层。因为我想首先使用WPF PURELY进行渲染,所以我想开发“Visual Layer”。
然后我遇到了类似的事情: DrawingVisual, GeometryDrawing, FrameworkElement / UIElement /形状
所以,我对所有不同的实现有点不知所措,它们以完全不同的方式最终完成相同的工作。
Graph-Node库已经用它的所有逻辑(包括碰撞检测和用鼠标拖动)移植到C#。因为它是用图形渲染器(如XNA,SlimDX,OpenTK等)制作的,所以在性能方面实现WPF渲染器的最佳方式(如同,它将绘制图形库告诉它的任何东西)画画?
基本上,生成的WPF控件充当画布,但它必须是SUPER轻量级,除了为我提供绘制圆圈,线条和其他形状的方法之外,没有任何简洁的WPF功能:)
编辑:
我基本上想知道:走的路是什么?我是否将Canvas扩展为我的图形的“主机”,然后添加我的UIElement的自定义实现?或者我可以拥有一个可以绘制一切的课程(例如,一个超级超级超级图形)。就像重写GDI中的OnPaint或Java中的Paint-method(它使Graphics对象可以完成所有操作)。
答案 0 :(得分:11)
我建议阅读Optimizing Performance: 2D Graphics and Imaging(死链接 - 通过互联网档案可读) -
基本上,Drawing
个对象的重量通常比Shapes
轻。这可能是你想要使用的。
答案 1 :(得分:5)
通常,使用较低级别的服务可以获得更好的性能。在WPF
中,这意味着Drawing
系列对象。您得到的只有:Drawing
,DrawingGroup
,GeometryDrawing
,GlyphRunDrawing
,ImageDrawing
和VideoDrawing
。但是,它们足以满足所有需求。使用这些类型对WPF非常友好,因为Drawing
是WPF与GPU加速器交换的概念单元,如果可能的话,可能会在那里保留和管理它。这是有效的,因为Drawing
是用便携式矢量绘图原语表示的。
然后,您开始围绕Drawings
重新构建应用程序时,可能需要与更高级别的代码进行互操作,该代码仍基于UIElement
,FrameworkElement
等。我没有找到WPF内置的东西是一种简单的方法,以尽可能低开销的方式将Drawing包装为FrameworkElement 。 DrawingVisual
不是一个完整的解决方案,因为它只来自Visual
- 意味着它仍然需要托管元素。
以下类将直接托管任何WPF Drawing
,而不使用中间DrawingVisual
。我添加了对FrameworkElement
的{{1}}属性的支持(如果未使用则不会造成性能损失)但除此之外几乎没有。由于WPF的单个渲染线程,缓存单个TranslateTransform对象以实现边距是安全且容易的。我建议您只提供已冻结的图纸;事实上,在我使用的版本中,我在构造函数中有一个断言。
Margin
[edit:]这对于将WPF public class DrawingElement : FrameworkElement
{
static readonly TranslateTransform tt_cache = new TranslateTransform();
public DrawingElement(Drawing drawing)
{
this.drawing = drawing;
}
readonly Drawing drawing;
TranslateTransform get_transform()
{
if (Margin.Left == 0 && Margin.Top == 0)
return null;
tt_cache.X = Margin.Left;
tt_cache.Y = Margin.Top;
return tt_cache;
}
protected override Size MeasureOverride(Size _)
{
var sz = drawing.Bounds.Size;
return new Size
{
Width = sz.Width + Margin.Left + Margin.Right,
Height = sz.Height + Margin.Top + Margin.Bottom,
};
}
protected override void OnRender(DrawingContext dc)
{
var tt = get_transform();
if (tt != null)
dc.PushTransform(tt);
dc.DrawDrawing(drawing);
if (tt != null)
dc.Pop();
}
};
插入Drawing
属性(即使用InlineUIContainer.Child
更丰富地格式化TextBlock的内容)也很有用。
答案 2 :(得分:0)
DrawingVisual似乎是一个有效的选择:
DrawingVisual是一个用于的轻量级绘图类 渲染形状,图像或文本。这个类被认为是轻量级的 因为它不提供布局或事件处理,这提高了 它的表现。因此,图纸非常适合背景 和剪贴画。
来源:Using DrawingVisual Objects
所以这似乎绝对是你要求的,Canvas SUPER轻量级。