--转载
在使用TabControl、ListView、Menu、TreeView的时候被各种Template搞得头昏眼花,决心把这个问题搞清楚,究竟什么时候该用什么Template?这是个麻烦的问题,欠揍的表达方法是“根据俺这么多年写程序的经验,这是一个需要经验才能解决的问题”。首先看一下相关几个类的层次结构:
Control
|
+---- ContentControl
| |
| +---- ListBoxItem
| |
| +---- HeaderedContentControl
| |
| +---- TabItem
|
+---- ItemsControl
|
+---- TreeView
|
+---- MenuBase
|
+---- HeaderedItemsControl
| |
| +---- MenuItem
| |
| +---- TreeViewItem
|
+---- Selector
|
+---- TabControl
|
+---- ListBox
值得关注的类有四个,为了简单清楚起见,给他们重新起名字:
- ContentControl:无标题的单元素容器
- HeaderedContentControl:有标题的单元素容器
- ItemsControl:无标题的多元素容器
- HeaderedItemsControl:有标题的多元素容器
各个类有不同的Template,引发我头疼症状的一共有3个,也给他们重新起名字:
- ContentTemplate:单元素的容器画单子元素的画笔
- ItemTemplate:多元素的容器画每个子元素的画笔
- HeaderTemplate:有标题的容器画标题的画笔
好,一切到目前为止都很清晰。再来看看各个类都有哪些画笔:
- ContentControl:无标题的单元素容器,只有画单子元素的画笔
- HeaderedContentControl:有标题的单元素容器,显而易见,比上面多了一个画标题的画笔
- ItemsControl:无标题的多元素容器,只有一个画每个子元素的画笔ItemTemplate
- HeaderedItemsControl:有标题的多元素容器,也是显而易见,多了一个画标题的画笔
同样,一切都是理所当然,显而易见。然而这时,混乱产生了:当“容器”和“元素”搭配到一起的时候,各种画笔就开始复杂起来了。现在来分析几个典型的容器和元素的搭配:
1、TabControl和TabItem
TabControl本身是一个无标题的多元素容器,按上面所述,没有标题画笔,只有一个画每个子元素的ItemTemplate画笔。
他肚子里的元素是TabItem,这是一个有标题的单元素容器,有两个画笔,ContentTemplate和HeaderTemplate。那么TabItem的画笔和TabControl的画笔是什么关系呢?
事实上我撒谎了:TabControl有两个画笔,ContentTemplate和ItemTemplate,而不是一个,其中ItemTemplate继承自父类,而ContentTemplate是他自己重新定义的一个属性——好,我们终于抓住了这个伪造身份证扰乱社会治安破坏和谐社会的家伙。这种做法虽然很混淆,但是带来了方便,容器和元素的对应关系是
他肚子里的元素是TabItem,这是一个有标题的单元素容器,有两个画笔,ContentTemplate和HeaderTemplate。那么TabItem的画笔和TabControl的画笔是什么关系呢?
事实上我撒谎了:TabControl有两个画笔,ContentTemplate和ItemTemplate,而不是一个,其中ItemTemplate继承自父类,而ContentTemplate是他自己重新定义的一个属性——好,我们终于抓住了这个伪造身份证扰乱社会治安破坏和谐社会的家伙。这种做法虽然很混淆,但是带来了方便,容器和元素的对应关系是
- TabItem的HeaderTemplate就是TabControl的ItemTemplate
- TabItem的ContentTemplate就是TabControl的ContentTemplate
2、Menu和MenuItem
Menu只有一个ItemTemplate,MenuItem有HeaderTemplate和ItemTemplate。这里其实有两个搭配,一个是Menu和MenuItem的搭配,另一个是MenuItem和MenuItem的搭配。在这两个搭配中,有以下共同点:
- 容器的ItemTemplate变成元素的HeaderTemplate
- 每个MenuItem都用自己对应的HeaderTemplate来显示自己
这是一个分级的结构,WPF提供了HierarchicalDataTemplate,很方便,不过暂时先不说这个,免得问题更加复杂化。
3、TreeView和TreeViewItem
从上面的类层次结构可以看出,这个搭配和Menu/MenuItem的情况应该是一样的,事实上在XAML中很容易在TreeView和Menu之间切换,容易到了只需要改几个tag就可以,可见两者是“同构”的。
4、ListBox和ListBoxItem
ListBox本身是一个无标题的多元素容器,只有一个ItemTemplate。ListBox是遵纪守法的好同志,不像TabControl伪造了一个ContentTemplate。他的ItemTemplate就是ListBoxItem的ContentTemplate,并且ListBoxItem也没有其他的画笔了,这一对组合是最简单的。