Как установить привязки к элементам управления внутри DataTemplate?

ItemsControl: как использовать FindName в ItemsPanelTemplate для доступа к панели

Доступ к дочернему элементу ListBoxItem

FindName MSDN

Доступ к элементу управления из DataTemplate с его идентифицирующим именем

Мне нужно написать пользовательский элемент управления, который принимает список T и отображает два свойства этого списка в ListBox, Имена отображаемых свойств списка будут свойствами моего элемента управления.

По сути, мне нужно воспроизвести функциональность ComboBox, копия ее ItemsSource, DisplaymemberPath а также SelectedValuePath свойства. Мне нужно показать свойства, указанные DisplayMemberPath а также SelectedValuePath в ListBox контроль.

По причинам, не относящимся к этому посту, я не могу повторить ComboBox, Так как я не могу получить доступ к элементам управления внутри DataTemplate (как описано здесь).

Мой вопрос: как мне установить привязки на PART_ListIDTextBlock а также PART_ListDescTextBlock указать на соответствующие свойства на ItemsSource? Опять же, код здесь не работает.

Обратите внимание, что я не спрашиваю, как найти элементы управления в DataTemplate, На основании таких ответов:

Доступ к элементам внутри DataTemplate... Как использовать более 1 DataTemplate?

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

<Style TargetType="{x:Type local:Selector}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:Selector}">
                <Border Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">
                    <StackPanel Orientation="{TemplateBinding Layout}">
                        <TextBox
                            x:Name="PART_IDTextBox" 
                            Margin="2"
                            MinWidth="30" />
                        <TextBox
                            x:Name="PART_DescTextBox" 
                            Margin="2"
                            MinWidth="30"
                            Grid.Column="1"/>

                        <Popup IsOpen="True">
                            <ListBox ItemsSource="{TemplateBinding ItemsSource}" x:Name="ListBox1" IsSynchronizedWithCurrentItem="True">
                                <ListBox.ItemTemplate>
                                    <DataTemplate> 
                                        <Grid>
                                            <Grid.ColumnDefinitions>
                                                <ColumnDefinition />
                                                <ColumnDefinition />
                                            </Grid.ColumnDefinitions>
                                            <TextBlock x:Name="PART_ListIDTextBlock" Margin="0,0,5,0" />
                                            <TextBlock x:Name="PART_ListDescTextBlock" Grid.Column="1"/>
                                        </Grid>
                                    </DataTemplate>
                                </ListBox.ItemTemplate>
                            </ListBox>
                        </Popup>
                    </StackPanel>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

    public string DisplayMemberPath { get; set; }  // Does not need to be a dependency property.  
    public string SelectedValuePath { get; set; }   // Does not need to be a dependency property.  

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();
        IDTextBox = Template.FindName("PART_IDTextBox", this) as TextBox;
        DescTextBox = Template.FindName("PART_DescTextBox", this) as TextBox;
        ListBox listBox = Template.FindName("ListBox1", this) as ListBox;
        listBox.Loaded +=new RoutedEventHandler(listBox_Loaded);
    }

    void listBox_Loaded(object sender, RoutedEventArgs e)
    {
        ListBox listBox = sender as ListBox;

        if (listBox.Items.Count == 0)
            return;

        // The following line fails because listBox.Items.CurrentItem is actually type of <T> and cannot be cast to type ListBoxItem
        ListBoxItem item = (ListBoxItem)(listBox.ItemContainerGenerator.ContainerFromItem(listBox.Items.CurrentItem));
        ContentPresenter presenter = FindVisualChild<ContentPresenter>(item);
        DataTemplate template = presenter.ContentTemplate;
        TextBlock descTextBlock = template.FindName("PART_ListDescTextBlock", presenter) as TextBlock;
        TextBlock idTextBlock = template.FindName("PART_ListIDTextBlock", presenter) as TextBlock;
        descTextBlock.SetBinding(TextBlock.TextProperty, new Binding { Source = ItemsSource, Path = new PropertyPath(DisplayMemberPath) });
        idTextBlock.SetBinding(TextBlock.TextProperty, new Binding { Source = ItemsSource, Path = new PropertyPath(SelectedValuePath) });
    }

0 ответов

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