强制 DataTemlate return 特定对象
Force DataTemlate to return a specific object
我正在编写一个新的 WPF 控件来绘制和编辑大量形状,比如数十万个。为此,我想让用户为他的数据定义 DataTemplate
。但是 LoadContent
这个特定的 DataTemplate
必须 return 特定的类型,IShape
。我怎样才能做到这一点?
首先,模板的全部意义在于支持插入任意 视觉树。如果您对模板的组成有严格的要求,那么使用模板是错误的设计选择。
其次,模板必须描述Visual
。如果您要绘制数十万个形状,您 将无法 将它们表示为视觉效果。视觉效果相当重量级
- 他们参与了输入命中测试。 (!)
- 它们拥有依赖对象的所有开销。
- 他们参与继承上下文。
- 他们必须将 属性 更改传达给他们的父级,即影响布局和渲染的属性。
- 它们可能包含动态资源引用,它们必须观察变化。
- 它们可能会延长更重的
UIElement
或 甚至更重的 FrameworkElement
,这意味着:
- 他们参与布局。 (!)
- 路由事件通过它们传递,并可能由它们处理。
- 他们可能正在使用数据绑定。
作为替代方案,我建议您提供一个界面,您可以通过该界面提供 几何数据 ,您可以冻结、共享、重用和高效渲染这些数据。这将允许您坚持使用 WPF 中可用的最低级别的图形 API 集。但是,老实说,即使那样也可能不够好。
但有一件事是肯定的:在 Visual Layer 中呈现所有这些形状是不可能的。我至少会实施某种形式的虚拟化,您可以在其中有效地仅定位视图中的那些形状(四叉树或类似的?),仅渲染视图中的几何体(使用裁剪),并使用缓存合成来避免不断重绘;重新镶嵌;如果实际上没有任何变化,则对几何体执行每个图元抗锯齿。
DataTemplate
return 模板内容的根元素的 LoadContent
方法。所以它只会 return 一个 IShape
如果用户(消费者)已经准确地将 IShape
定义为模板中的根元素。
但是您不能真正强制 class 的消费者将 DataTemplate
类型的 属性 设置为 DataTemplate
保证包含 IShape
。消费者不妨将 属性 设置为仅包含 Button
.
的 DataTemplate
你可以做的是在运行时抛出一个InvalidOperationException
,如果LoadContent
方法[=47] =]s 除了 IShape
以外的任何东西。但是,您不能在编译时做出任何保证。但这就是 DataTemplates
的工作方式。
也许您应该考虑让用户设置 IShape
属性 而不是 DataTemplate
属性。您可以让 IShape
(或 Shape
)成为某种 ContentControl
或 UserControl
。
毕竟,DataTemplate
是一个可能包含任何 UIElement
.
的 模板
我正在编写一个新的 WPF 控件来绘制和编辑大量形状,比如数十万个。为此,我想让用户为他的数据定义 DataTemplate
。但是 LoadContent
这个特定的 DataTemplate
必须 return 特定的类型,IShape
。我怎样才能做到这一点?
首先,模板的全部意义在于支持插入任意 视觉树。如果您对模板的组成有严格的要求,那么使用模板是错误的设计选择。
其次,模板必须描述Visual
。如果您要绘制数十万个形状,您 将无法 将它们表示为视觉效果。视觉效果相当重量级
- 他们参与了输入命中测试。 (!)
- 它们拥有依赖对象的所有开销。
- 他们参与继承上下文。
- 他们必须将 属性 更改传达给他们的父级,即影响布局和渲染的属性。
- 它们可能包含动态资源引用,它们必须观察变化。
- 它们可能会延长更重的
UIElement
或 甚至更重的FrameworkElement
,这意味着:- 他们参与布局。 (!)
- 路由事件通过它们传递,并可能由它们处理。
- 他们可能正在使用数据绑定。
作为替代方案,我建议您提供一个界面,您可以通过该界面提供 几何数据 ,您可以冻结、共享、重用和高效渲染这些数据。这将允许您坚持使用 WPF 中可用的最低级别的图形 API 集。但是,老实说,即使那样也可能不够好。
但有一件事是肯定的:在 Visual Layer 中呈现所有这些形状是不可能的。我至少会实施某种形式的虚拟化,您可以在其中有效地仅定位视图中的那些形状(四叉树或类似的?),仅渲染视图中的几何体(使用裁剪),并使用缓存合成来避免不断重绘;重新镶嵌;如果实际上没有任何变化,则对几何体执行每个图元抗锯齿。
DataTemplate
return 模板内容的根元素的 LoadContent
方法。所以它只会 return 一个 IShape
如果用户(消费者)已经准确地将 IShape
定义为模板中的根元素。
但是您不能真正强制 class 的消费者将 DataTemplate
类型的 属性 设置为 DataTemplate
保证包含 IShape
。消费者不妨将 属性 设置为仅包含 Button
.
DataTemplate
你可以做的是在运行时抛出一个InvalidOperationException
,如果LoadContent
方法[=47] =]s 除了 IShape
以外的任何东西。但是,您不能在编译时做出任何保证。但这就是 DataTemplates
的工作方式。
也许您应该考虑让用户设置 IShape
属性 而不是 DataTemplate
属性。您可以让 IShape
(或 Shape
)成为某种 ContentControl
或 UserControl
。
毕竟,DataTemplate
是一个可能包含任何 UIElement
.