修改或“调整”现有的TreeViewItem控件模板?

时间:2010-09-30 04:22:12

标签: wpf templates treeview treeviewitem

好的......这有点像两个人。 (实际上只是一个。这就是我所希望的。)

首先,更一般地说,是否可以仅通过XAML定位控件的模板中的命名项?例如,如果控件的模板有一个名为“PART_Foo”的ContentPresenter,并且我们想通过纯样式专门将该特定项目上的Horizo​​ntalAlignment设置为“Stretch”,那么它可以完成吗?我知道我们可以在子类的OnApplyTemplate重写中执行此操作,其中我们通过名称显式搜索控件然后在代码中设置属性,但同样,我们希望只使用XAML解决方案,因此我们可以通过样式严格执行此操作而不是子类,除了特定的用例场景之外,最常不鼓励这些子类。

此外,我们希望手动指定控件的模板,因为我们希望当前主题确定该模板是什么,从而确定控件的显示方式。我们只想说'在主题选择的任何模板中,如果有一个名为'foo'的部分,则通过纯样式设置此属性。如果找不到具有该名称的部件,则不执行任何操作!

对于仅使用XAML的方法的需求更多是因为第二部分,即我们的目标是生成的容器对象,而不是控件本身,这意味着它不会像我们一样直接的子类。用ItemcontainerGenerators等来解决这个问题,这在a $$中是一个真正的痛苦,特别是当ItemsControl被虚拟化时。

具体来说,我们的最终目标是在TreeView的TreeViewItem模板中挑出名为'Bd'的Border,并将其附加属性'Grid.ColumnSpan'设置为'2'而不是默认值'1'。而已!令人惊讶的是,如果没有手动替换整个TreeViewItem的模板或采用基于代码隐藏的解决方案,那么如此简单的事情几乎是不可能的。

1 个答案:

答案 0 :(得分:0)

不,仅使用XAML是不可能的。你至少必须为此编写一个附加属性(然后你可以在XAML中使用它)。只有当您在运行时没有动态创建任何控件时,这才会起作用,因为它发生在虚拟化列表中。它看起来像这样:c:TemplateHelper.ReplaceStretchForTemplateItemName="PART_Foo"。在更改的处理程序中,您将使用VisualTreeHelper遍历该控件的可视子树,并查找该名称并应用您想要的任何内容。

修改像这样的模板是有缺陷的,并且被认为是不好的做法。非常喜欢有一个主题或将来没有“Part_Foo”或者“Part_Foo”与你预期的完全不同的主题。主题以及ControlTemplates可能会发生变化。当Microsoft更新其操作系统时,将出现(并自动应用于您的应用程序)新主题,如果您支持自定义主题,则设计人员可能会提出不同的主题。

你可能会认为这是ControlTemplates的一个缺点,并且它可以扩展到它。但是再次尝试在Windows窗体(或这个星球上的任何其他UI框架)中自定义控件...... 只是当习惯了WPF的巨大可能性时,更难以接受限制,在这种情况下,这些限制是设计的。