2010-08-10 4 views
5

Мне не удалось найти решение для решения следующих проблем, хотя есть несколько связанных вопросов уже на SO.Элемент доступа внутри Silverlight DataTemplate

Если у меня есть шаблон данных, который используется несколько раз, например TreeViewItem.HeaderTemplate, как я могу что-то изменить шаблон только для некоторых из TreeViewItems.

Например, у моего TVI HeaderTemplate есть текстовый блок, и в зависимости от строки я хочу сделать шрифт полужирным.

Я хочу сделать что-то вроде этого:

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

Кто-нибудь есть решение для этого? -> Thanks Evan

Редактировать: Есть ли способ написать общую функцию для получения элемента управления на основе его имени, даже если он находится в шаблоне данных?

LayoutRoot.FindName("myTextBlock"); будет работать, если myTextBlock не был вставлен в datatemplate. Как написать функцию findElementInDataTemplate(string elementName, string parentName)?

Причина ответа Эвана не в том, что я ищу, потому что я разрабатываю элемент управления. Я хочу, чтобы разработчик приложения, который использует мой элемент управления, мог изменить любой элемент в элементе управления. Если я использую решение Evan, это потребует, чтобы разработчик приложения имел доступ ко всем шаблонам в элементе управления. Возможно, но не идеально. Благодаря!

+0

Если вы использовали DataTemplate, который содержит элемент управления под названием «myTextBlock» несколько раз, а затем иметь какое-то 'LayoutRoot.FindName («myTextBlock») 'операция, какая из многих элементов управления, называемая« myTextBlock », вы хотите вернуть эту операцию? – AnthonyWJones

+0

@ AnthonyWJones Хорошая точка, отредактированная для включения параметра parentName. – NickHalden

+0

@AnthonyWJones: Обычно два элемента управления с именем невозможно. если вы сохраняете два одинаковых элемента управления в шаблоне, то шаблон считается неправильным. – Mahantesh

ответ

0

какая версия серебряного света это? А какой год «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

1

Моей первой реакцией на такое требование было бы: вы действительно уверены, что хотите это сделать? Обычно я призываю разработчиков взглянуть на существующие шаблоны управления. В этом случае кажется, что вам кажется, что шаблонный контроль выглядит оправданным.

Конечно, это не дает вам гибкости. Кажется, что вам кажется, что это «священный грааль» настраиваемых элементов управления, желание изменить любые мелкие детали контроля, не дублируя весь шаблон элемента управления. Конечно, это на самом деле невозможно декларативно, если бы я боялся синтаксиса и семантических правил, которые бы управляли им.

Сказав, что всегда есть исключения. Поэтому я представлю возможный вариант, несмотря на то, что вы не должны этого делать.

Этот старый answer предоставляет метод расширения Descendents, позволяющий перечислить элементы управления по дереву объектов. Учитывая экземпляр TreeViewItem вы должны быть в состоянии найти TextBlock вы после с: -

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

Я получаю сообщение об ошибке. Объект зависимостей IEnumerable не содержит определения для TypeOf – NickHalden

+0

@JGord: убедитесь, что вы включили 'using System.Linq' в начало вашего файла кода. – AnthonyWJones

+0

Уже было, что там, другие возможные ловушки? – NickHalden

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

0

можно также попробовать этот

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

где грд = ваш корневой элемент (Parent элемента, которого вы ищете)

Смежные вопросы