2010-08-10 65 views
5

即使在SO上已经有几个相关的问题,我仍然无法找到以下问题的干净解决方案。访问Silverlight DataTemplate中的元素

如果我有一个多次使用的数据模板,例如TreeViewItem.HeaderTemplate,我如何才能更改某些TreeViewItems的模板。

例如,假设我的TVI HeaderTemplate有一个文本块,并且取决于字符串,我想使得这个文本的粗体。

我想要做这样的事情:

((TextBlock)myTreeView.Items.ElementAt(0).FindName("myTextBlock")).FontWeight = FontWeights.Bold; 

有没有人有一个解决方案? - >谢谢埃文

编辑:有没有办法编写一个通用函数来获取控件的基础上,即使它是在一个数据模板的名称?

LayoutRoot.FindName("myTextBlock");将工作,如果myTextBlock不在数据模板中。我怎么写一个findElementInDataTemplate(string elementName, string parentName)函数?

Evan的答案不是我正在寻找的原因是因为我正在开发一个控件。我希望使用我的控件的应用程序开发人员能够更改控件中的任何元素。如果我使用Evan的解决方案,则需要应用程序开发人员访问控件中的所有模板。可能,但不理想。谢谢!

+0

如果您使用的是含有一种叫“myTextBlock”多次,然后控制一个DataTemplate(你正在寻找的元素的父)有某种LayoutRoot.FindName的'( “myTextBlock”)'操作,那么称为“myTextBlock”的许多控件中的哪一个会让该操作返回? – AnthonyWJones 2010-08-10 16:54:11

+0

@AnthonyWJones好点,编辑后包含一个parentName参数。 – NickHalden 2010-08-10 17:04:59

+0

@AnthonyWJones:通常情况下,名称的两个控件是不可能的。如果您在模板中保留两个相同的名称控件,则模板被认为是错误的。 – Mahantesh 2012-02-06 10:52:18

回答

0

这是什么版本的silverlight? “8月10日18:55”是哪一年?

在当前版本SL4它似乎并没有在那里

..

2

如果您使用数据绑定,您是否尝试过使用绑定转换器?在这种情况下,你会做这样的事情......

FontWeight={Binding Path=TextProperty, Converter={StaticResource BoldConverter}} 

和转换器将沿着线...

string myTestString = (string)value; 
if (myTestString.Contains("Bob")) 
    return FontWeights.Bold; 
return FontWeights.Normal; 

这使得其痛苦的尝试和根通过元素找到一个特定的。

+0

伟大的解决方案,我的问题。现在让我们假装我问了我真正的意思,查看我的编辑。 – NickHalden 2010-08-10 16:08:58

1

我对这样的要求的第一反应是:你真的确定你想要这样做吗?我通常会敦促开发人员查看现有的控制模式。在这种情况下,你看起来似乎是一个模板控制似乎是有保证的。

当然这并不能提供您所追求的灵活性。你似乎在追求的是可定制控件的“圣杯”,希望能够调整关于控件的任何细节,而不必复制整个控件的模板。当然,这不是真的可以用声明来说明,如果是我会害怕将管理它的语法和语义规则。

话虽如此,总有例外。所以我会提出一个可能的选择,尽管感觉你不应该这样做。

这个旧的answer提供了一个Descendents扩展方法,允许您枚举整个对象树中的控件。给定一个TreeViewItem的实例,你应该能够找到TextBlock你是后: -

我已经完成了这个
TextBlock tb = treeViewItem.Descendents() 
       .OfType<TextBlock>() 
       .Where(t => t.Name == "myTextBlock") 
       .FirstOrDefault(); 
+0

我收到错误消息IEnumerable依赖项对象不包含TypeOf的定义 – NickHalden 2010-08-10 18:27:46

+0

@JGord:确保您在代码文件的顶部包含'using System.Linq'。 – AnthonyWJones 2010-08-10 19:41:52

+0

已经有在那里,其他可能的陷阱? – NickHalden 2010-08-10 20:17:40

4

一种方式是通过使用所有的类级集合变量所需的物品存储Loaded事件的控件。以此DataTemplate为例。

<DataTemplate> 
    ... 
    <TextBlock Loaded="TemplateTextBlock_Loaded" /> 
</DataTemplate> 

然后,您使用Loaded事件加载某种集合以备后用。

private List<TextBlock> templateTextBlocks = new List<TextBlock>(); 

private void TemplateTextBlock_Loaded(object sender, RoutedEventArgs e) 
{ 
    TextBlock tb = sender as TextBlock; 
    if (!this.templateTextBlocks.Contains(tb)) this.templateTextBlocks.Add(tb); 
} 

当然,如果您打算加载和卸载控件,这可能对您不适用。

+0

这对我有用,AnthonyWJones的答案在视觉树已经生成时很有用,但是这个在那之前也有效 – hungryMind 2013-01-10 14:16:36

0

也可以尝试这个

的TextBlock txtBlk = grd.FindName( “txtBlkName”)作为TextBlock的;

其中GRD =您的根元素