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

发布于 2024-09-25 15:51:10 字数 798 浏览 0 评论 0原文

好吧……这里有点像两部分。 (有点。实际上可能只是一个。无论如何,这就是我所希望的。)

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

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

对仅 XAML 方法的渴望更多是因为第二部分,即我们的目标是生成的容器对象,而不是控件本身,这意味着它无论如何都不会是直接子类,因为我们必须四处乱搞使用 ItemcontainerGenerators 等,这对 a$$ 来说是一个真正的痛苦,特别是当 ItemsControl 被虚拟化时。

具体而言,我们的最终目标是在 TreeView 的 TreeViewItem 模板中挑选出名为“Bd”的边框,并将其附加属性“Grid.ColumnSpan”设置为“2”,而不是默认值“1”。就是这样!让我惊讶的是,如果不手动替换整个 TreeViewItem 的模板或诉诸基于代码隐藏的解决方案,如此简单的事情似乎几乎是不可能的。

Ok... this is sort of a two-parter here. (Sort of. May actually just be one. That's what I'm hoping anyway.)

First, more generally, is it possible to target, via XAML only, a named item in a control's template? For instance, if a control's template has a ContentPresenter named 'PART_Foo' and we want to specifically set the HorizontalAlignment on that specific item to 'Stretch' via pure styling, can it be done? I know we can do this in the OnApplyTemplate override of a subclass where we explicitly search for the control by name then set the property in code, but again, we're hoping for a XAML-only solution so we can do this strictly via styling and not subclasses, which are mostly discouraged anyway except for specific use-case scenarios.

Also, we do not want to have to manually specify the template for the control as we want the current theme to determine what that template is and thus how the control appears. We just want to say 'In whatever template the theme has chosen, if there's a part named 'foo', set this property on it via pure styling. If a part with that name isn't found, do nothing!

The desire for a XAML-only approach is more because of the second part, which is we're targeting a generated container object, not the control itself, meaning it wouldn't be a straight subclass anyway as we'd have to muck around with ItemcontainerGenerators and such, which is a real pain in the a$$, especially when the ItemsControl is virtualized.

For specifics, our ultimate goal is to single out the Border named 'Bd' in a TreeView's TreeViewItem's template and set its attached property 'Grid.ColumnSpan' to '2' instead of its default of '1'. That's it! It amazes me how something so simple seems damn near impossible without manually replacing the entire TreeViewItem's template or resorting to a code-behind-based solution.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

人间不值得 2024-10-02 15:51:10

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

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

您可能会说这是 ControlTemplates 的一个缺点,在某种程度上确实如此。但是,再次尝试在 Windows 窗体(或这个星球上的任何其他 UI 框架)中自定义控件...
只是当习惯了 WPF 的巨大灵活性时,就很难接受限制,在本例中,这些限制是设计使然的。

No, this is not possible using XAML only. You would at least have to write an attachted property for this (wich you then could use in XAML). And that would only work if you do not have any controls being created on the fly at runtime as it happens in virtualized lists. It would look something like this: c:TemplateHelper.ReplaceStretchForTemplateItemName="PART_Foo". In the changed handler you would walk the visual sub tree of that control using VisualTreeHelper and look for that name and apply whatever you want.

Modifying the a template like this is flawed tough and considered to be bad practise. It is very likeley that there is a theme or will be in the future that does not have "Part_Foo" or that "Part_Foo" is something completely different than you expected it to be. Themes and thus the ControlTemplates are subject to change. New themes will appear (and automatically applied to your application) as Microsoft updates its operating systems and if you support custom themes you designers might come up with a theme that is different.

You could argue that this a disadvantage of ControlTemplates and it to some extend it is. But then again try customizing Controls in windows forms (or any other UI framework on this planet)...
It's just that when getting used to the immense felxibilty of WPF it's harder to accept limitations, which in this case are by design.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文