2010-07-29 3 views
4

Допустим, я создал UserControl со следующим ContentTemplate, определенным в XAML:Как я могу программно обращаться к элементам, определенным в ContentTemplate?

<UserControl.ContentTemplate> 
    <DataTemplate> 
     <Ellipse Name="myEllipse" Stroke="White"/> 
     <ContentPresenter Content="{TemplateBinding Content}"/> 
    </DataTemplate> 
</UserControl.ContentTemplate> 

Как бы я получить доступ к элементу «myEllipse» в моем коде, так что, к примеру, я мог бы найти его высоту с " myEllipse.Height "? Я не могу получить доступ к нему по имени напрямую. Я попытался создать ссылку на него с:

Ellipse ellipse = ContentTemplate.FindName("myEllipse",this) as Ellipse; 

Это происходит сбой при запуске программы, заявив, что не может создать экземпляр моего класса. Возможно, я неправильно использую FindName. Если кто-нибудь сможет мне помочь, это будет очень признательно.

Спасибо,

Dalal

ответ

5

Для того, чтобы использовать FindName на DataTemplate, вам нужна ссылка на ContentPresenter. См. Статью Джоша Смита How to use FindName with a ContentControl.

Что вы можете на самом деле хотите сделать, это использовать ControlTemplate, а не DataTemplate. Это должно быть проще в использовании и позволит пользователям вашего контроля применять собственные шаблоны контента или использовать неявные шаблоны. Если вы делаете что-то вроде этого:

<UserControl.Template> 
    <ControlTemplate TargetType="UserControl"> 
     <Grid> 
      <ContentPresenter/> 
      <Ellipse Name="myEllipse" Stroke="White"/> 
     </Grid> 
    </ControlTemplate> 
</UserControl.Template> 

Затем в коде (возможно, в качестве OnApplyTemplate переопределение) вы будете в состоянии сделать это:

var ellipse = Template.FindName("myEllipse", this) as Ellipse; 

Вы также должны украсить свой класс с TemplatePartAttribute, как это :

[TemplatePart(Name="myEllipse", Type = typeof(Ellipse))] 

Так что, если кто-то переустанавливает ваш контроль, который, как известно, предоставляет элемент Ellipse с этим именем. (Это менее важно, если класс используется только внутри.)

Наконец, если все, что вы хотите сделать, это изменить цвет эллипса, тогда вы можете просто использовать привязку данных. Вы можете создать свойство зависимостей EllipseColor на своем элементе управления и просто установить Stroke="{TemplateBinding EllipseColor}".

+0

Спасибо за очень информативный ответ. Я попытался использовать ControlTemplate вместо моего DataTemplate, но мой UserControl не выглядел одинаково, и некоторые функции были затронуты, поэтому я бы скорее попытался заставить его работать с DataTemplate, теперь, когда я получил это далеко в мой контроль развития. После прочтения статьи Джоша Смита я попытался поместить следующую строку в конструктор для моего управления: ContentPresenter contentPresenter = VisualTreeHelper.GetChild (this, 0) as ContentPresenter; К сожалению, он не работает на этой линии. Я получаю исключение синтаксиса XAML. Есть идеи? – Dalal

+1

@Dalal: визуальное дерево еще не заполнено в конструкторе, поэтому вы получаете исключение вне диапазона в вызове GetChild.Это заверяется в исключение синтаксиса XAML, поскольку он не смог создать экземпляр вашего объекта. Вам нужно будет переместить код в обработчик события загрузки или переопределить OnApplyTemplate. Кроме того, шаблон управления по умолчанию для UserControl имеет ContentPresenter в Border, поэтому 'VisualTreeHelper.GetChild (this, 0)' вернет границу. Вам нужно будет сделать что-то вроде «VisualTreeHelper.GetChild (VisualTreeHelper.GetChild (this, 0), 0)». – Quartermeister

+0

В моем переопределении OnApplyTemplate я смог успешно получить ContentPresenter, используя строку 'VisualTreeHelper.GetChild (VisualTreeHelper.GetChild (this, 0), 0) как ContentPresenter;' Теперь мне нужно было получить ссылку на один из моих объектов с именем ' headerLabel ', поэтому я помещаю 'headerLabel = ContentTemplate.FindName (" headerLabel ", contentPresenter) в качестве метки:' Я получаю InvalidOperationException: эта операция действительна только для элементов, которые применяют этот шаблон. Ну, учебник сказал, чтобы пройти в ContentPresenter. Я сделал. Я также попытался помещать этот код в событие MouseDown безрезультатно. – Dalal

0

Попробуйте

<Ellipse Name="myEllipse" Stroke="{TemplateBinding Background}"/> 

вместо программно изменить его.

Здесь приведен пример с синим заполненным эллипсом. http://msdn.microsoft.com/en-us/library/system.windows.controls.contentpresenter.aspx

+0

Моя проблема заключается в получении ссылки на объект, не изменяя его ход. Я использовал штрих как пример, но теперь я отредактирую его, так как это было немного неясно. Благодарю. – Dalal

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