【问题标题】:Access Element inside Silverlight DataTemplateSilverlight DataTemplate 中的访问元素
【发布时间】:2010-08-10 15:27:50
【问题描述】:

即使在 SO 上已有一些相关问题,我也无法找到以下问题的干净解决方案。

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

例如,假设我的 TVI HeaderTemplate 有一个文本块,根据字符串,我想将 fontweight 设为粗体。

我想做这样的事情:

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

有人对此有解决方案吗? --> 谢谢埃文

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

LayoutRoot.FindName("myTextBlock"); 如果 myTextBlock 不在数据模板中,则可以使用。如何编写findElementInDataTemplate(string elementName, string parentName) 函数?

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

【问题讨论】:

  • 如果您多次使用了包含名为“myTextBlock”的控件的 DataTemplate,然后进行了某种LayoutRoot.FindName("myTextBlock") 操作,那么您希望该操作在众多名为“myTextBlock”的控件中的哪一个返回?
  • @AnthonyWJones 好点,已编辑以包含 parentName 参数。
  • @AnthonyWJones:通常两个具有名称的控件是不可能的。如果您在模板中保留两个同名控件,则模板被认为是错误的。

标签: c# silverlight silverlight-3.0 datatemplate


【解决方案1】:

我完成此操作的一种方法是使用控件的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);
}

当然,如果您要加载和卸载控件,这可能不适合您。

【讨论】:

  • 这对我有用,AnthonyWJones 的答案在已经生成可视化树时很有用,但在此之前也可以使用
【解决方案2】:

如果您使用数据绑定,您是否尝试过使用绑定转换器?在这种情况下,您会执行类似...

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

转换器将遵循...

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

这使得尝试通过元素查找特定元素变得不那么痛苦。

【讨论】:

  • 很好地解决了我的问题。现在让我们假装我问了我真正想说的问题,看看我的编辑。
【解决方案3】:

我对这样的要求的第一反应是:你真的确定要这样做吗?我通常会敦促开发人员查看正在使用的现有控制模式。在这种情况下,您似乎需要使用模板化控件。

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

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

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

TextBlock tb = treeViewItem.Descendents()
                 .OfType<TextBlock>()
                 .Where(t => t.Name == "myTextBlock")
                 .FirstOrDefault();

【讨论】:

  • 我收到错误消息 IEnumerable 依赖对象不包含 TypeOf 的定义
  • @JGord:确保您在代码文件的顶部包含了using System.Linq
  • @JGord:糟糕,我的错!它的OfType 不是TypeOf,相应地进行了编辑。
【解决方案4】:

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

在当前版本的 SL4 中,它似乎不存在..

【讨论】:

    【解决方案5】:

    也可以试试这个

    TextBlock txtBlk = grd.FindName("txtBlkName") as TextBlock;

    其中 grd = 您的根元素(您要查找的元素的父级)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-05
      • 1970-01-01
      • 2011-03-02
      • 1970-01-01
      • 2011-09-11
      • 2013-12-10
      相关资源
      最近更新 更多