《Programming WPF》翻译 第9章 2.选择一个基类
WPF提供了很多类,当创建一个自定义元素时,你可以从这些类中派生。图9-1显示了一组可能作为类——可能是合适的基类,并且说明了他们之间的继承关系。注意到,这决不是完整的继承关系图,只是简单的显示了一些你应该考虑的可能的基类。
无论你选择了哪一个基类,你的元素都会直接或间接地从FrameworkElement派生。这将提供routing事件,高级属性处理,动画,数据绑定,外观上的支持,样式,以及逻辑树的集成。
派生于FrameworkElement并不是绝对的需要。第7章讨论了底层可视化图形API,虽然该章的示例派生自FrameworkElement,你也可以直接派生于Visual,当使用底层绘图API的时候。然而,如果你这么做了,你将会损失由FrameworkElement提供的全部服务。对派生于底层的元素,你只能在特别专业的环境使用到。
图9-1
直接派生自FrameworkElement,对于一个被设计为组合到其他元素的元素而言,是恰当的。例如,考虑一个绑定到数据源而且生成数据图表的元素。你可能使之派生自Control。尽管如此,未经加工的图形绘制的元素,通常协力于其他元素如TextBlock,从而为这个图形和其轴提供标签。因此,将graph分成图形绘制可能是有意义的,这将合并到一个外观中,包含着任意数量的不同控件。
将一个控件放在另一个控件的模板内部是可行的。但是一旦你发现纯粹是在写一个自定义控件,并放在另一个控件的模板内,你可能需要回顾一下你选择的基类了。
如果你写一个表现自定义外观逻辑的元素,你应该派生于Panel,从而与内嵌外观元素保持一致。
如果你写一个包着另一个元素的元素——在某些方面的增强,要考虑派生于Decorator。很多内嵌元素都是派生于Decorator。例如,Border,在元素的外面添加了一个边框;还有Viewbox,可以自动伸缩被其包着的元素,填充有效的空间。如果你希望提供一种包装器,在内容外添加功能,要考虑派生于Decorator。
如果你的元素提供了行为,或支持用户交互动作——不能使用内嵌组件,这时派生于Control就是恰当的了,以直接或间接的方式。例如,如果你想制作一个交互式的图表组件,用户可以在上面点击图表中的数据项来检查它们,或者放大,这可以被典型地写为一个控件(同时可能要使用你先前写的表现底层图像的元素)。
Control提供了很多派生类,增强了基础控件的功能性。如果你写了一个控件,提供了空白区域,用户可以在上面防止一些内容(如一个标题),你应该派生于ContentControl,这个基类提供了支持内容模型的控件。如果你的控件支持在头标题以及主区域(如分页TabPage)的中的内容,要考虑派生于HeaderedContentControl。
如果你需要表现多个子元素,首先要考虑ListBox和数据绑定以及数据样式的联合是否满足你的需求。数据绑定和样式支持WPF的ListBox处理宽范围的场景,这些都是Win32和Windows Forms的ListBox所不适合的。一旦你需要额外的功能——内嵌的列表控件并不支持,你应该考虑派生于你的自定义元素类型,如Selector或其基类,如ItemControl。ItemControl对包含了列表项的控件提供了基本支持,包括可选的数据绑定功能。Selector增强了跟踪当前一个或一组选项的功能。