访问 DataTemplate 内的元素...如何访问超过 1 个 DataTemplate?
我为列表框控件定义了 2 个数据模板。 1 个模板用于未选定状态,另一个模板用于选定状态(显示比未选定状态更多的详细信息)。
我按照这里的示例:
关于如何从代码隐藏中访问 DataTemplates 内的元素的链接。
我的理解是正确的,但它只查找并返回未选定的 DataTemplate 的元素。但是,当我在选定的 DataTemplate 中搜索元素时,我收到 NullReferenceException。
我可能做错了什么?
I've got 2 DataTemplates defined for a Listbox Control. 1 Template is for the UnSelected State and the other one is for the Selected State(showing more detail than the UnSelected State).
I followed the example here:
about how to access the Elements inside the DataTemplates from Code behind.
I get it right, but it only finds and returns an element of the UnSelected DataTemplate. But when i search for an element in the Selected DataTemplate i get a NullReferenceException.
What could i be doing wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
设置键盘焦点可能是您需要访问数据模板元素的原因之一。 MVVM 无法解决该问题,并且 FocusManager 不会设置键盘焦点。
Setting keyboard focus might be one reason you need to access the datatemplate elements. MVVM will not solve that issue and the FocusManager doesn't set keyboard focus.
你做错了什么?
我想说你做错的是试图从代码隐藏中访问DataTemplate内的元素。顽皮,顽皮!
不开玩笑了,99.9% 的情况下我看到有人试图从代码访问 DataTemplate 内的元素,这是因为他们的应用程序设计得很糟糕,没有(或很少)绑定,也根本没有视图模型。许多初学者倾向于将数据直接存储在 UI 元素中,而不是使用视图模型。我认为这是因为他们的思想已经被 VB、WinForms 和 ASP.NET 的经验所腐蚀,在这些地方这是“正常”的方法。使用视图模型并绑定数据而不是将数据存储在 UI 元素中的原因有一千个。在线查找“模型视图视图模型”以获取更多详细信息。
现在回答您的问题:
任何给定的 ListBoxItem 一次只能有一个 DataTemplate。这是因为它的 ContentPresenter 只有一个 ContentTemplate 属性,并且该属性不能有两个不同的值。
因此,ListBoxItem 下的可视化树将始终从一个特定模板生成,而不是多个模板的组合。如果更改 ListBox 的 ItemTemplate 或以其他方式更新 ListBoxItem.ContentTemplate,则旧模板生成的可视化树将被丢弃,并构建新的可视化树。
我再说一遍:如果更改数据模板,旧数据模板生成的可视化树将被丢弃,并构建新的可视化树。
您可以在给定的 ListBoxItem 上定义并使用一百个数据模板,但一次只能为一个实例化可视化树。这些是作为视觉树的一部分实际存在的唯一元素。所有其他模板仅作为模板存在 - 没有为它们创建实际的元素。
换句话说:询问如何在同一控件上的两个不同模板实例化的两个不同视觉树中查找元素是没有意义的,因为单个控件不能同时激活两个不同的模板。
希望这能为您解决问题。
最后的建议:请阅读 MVVM,并尽快停止尝试访问 DataTemplates 内的元素。但是,如果您认为自己可能属于那 0.1% 的人,实际上确实有正当理由访问模板内的元素,请写回您想要这样做的实际原因,也许我可以提供进一步的指导。
What you are doing wrong?
I would say what you are doing wrong is trying to access elements inside the DataTemplate from code-behind. Naughty, naughty!
All joking aside, 99.9% of the time I see someone trying to access an element inside a DataTemplate from code, it is because their application is poorly designed, with no (or few) bindings and no view model at all. Many beginners tend to store their data directly in UI elements rather than using a view model. I think it is because their minds have been corrupted by experience VB, WinForms, and ASP.NET where it was the "normal" way to do it. There are a thousand reasons to use a view model and bind your data instead of storing them in UI elements. Look up "model view view model" online for more details.
Now to answer your question:
Any given ListBoxItem can only have one DataTemplate at a time. This is because its ContentPresenter has only one ContentTemplate property, and this property cannot have two different values.
Because of this, the visual tree under a ListBoxItem will always be generated from one a specific template, not a combination of several templates. If you change the ItemTemplate of the ListBox or otherwise update ListBoxItem.ContentTemplate, the visual tree produced by the old template will be thrown away and a new one built.
Let me say that again: If you change data templates, the visual tree produced by the old data template will be thrown away and a new visual tree built.
You can have a hundred data templates defined and usable on a given ListBoxItem, but only one at a time can have a visual tree instantiated for it. And these are the only elements that actually exist as part of the visual tree. All other templates exist only as templates - there are no actual elements created for them.
To put it another way: It is meaningless to ask about how to find elements in two different visual trees instantiated by two different templates on the same control, because a single control cannot have two different templates active at the same time.
Hope this clears things up for you.
Final advice: Do read up on MVVM, and stop trying to access elements inside DataTemplates ASAP. However if you think you might be in that 0.1% who actually do have valid reasons to access elements inside templates, write back with your actual reason for wanting to do so and maybe I can provide further guidance.