Программный доступ к элементу управления из DataTemplate

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

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

Фактически, в этом сценарии обработка событий вообще не работает и вызывает исключение OutOfMemoryException. Вот моя попытка:

Generic.xaml:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:SilverlightTest">


    <Style TargetType="local:TemplatedControl">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:TemplatedControl">
                    <ListBox ItemsSource="{TemplateBinding ListBoxItemsSource}">
                        <ListBox.ItemTemplate>
                            <DataTemplate>
                                <TextBlock x:Name="SomeTextBlock"
                                    Loaded="SomeTextBlock_Loaded"/>
                            </DataTemplate>
                        </ListBox.ItemTemplate>
                    </ListBox>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

templatedcontrol.cs:

public class TemplatedControl : Control
    {
        public object ListBoxItemsSource
        {
            get { return (object)GetValue(ListBoxItemsSourceProperty); }
            set { SetValue(ListBoxItemsSourceProperty, value); }
        }

        public static readonly DependencyProperty ListBoxItemsSourceProperty =
            DependencyProperty.Register
            ("ListBoxItemsSource", typeof(object),
             typeof(TemplatedControl), new PropertyMetadata(null));

        public TemplatedControl()
        {
            this.DefaultStyleKey = typeof(TemplatedControl);
        }

        public void SomeTextBlock_Loaded(object sender, RoutedEventArgs ea)
        {
        }
    }

1 ответ

Решение

У вас может быть другой элемент управления в вашем DataTemplate, чтобы справиться с этим, но это немного запутанно и с оговоркой "если вы действительно не верите, что логика оправдывает это".

Возможно, вы захотите переосмыслить свой подход. На мой взгляд (и это просто мнение!), Код должен связывать код только в более экзотических ситуациях.

Возможно, вместо использования IValueConverter, свяжите со свойством в ViewModel (предполагая, что ваш ItemsSource является коллекцией ViewModels), и позвольте вашей виртуальной машине соответствующим образом преобразовать ваши значения. Позвольте вашему стилю по умолчанию для этого элемента управления быть универсальным и уродливым и, возможно, использовать определенные стили для случаев, когда вам нужно привязать к определенным свойствам.

Другие вопросы по тегам