Как установить привязки к элементам управления внутри DataTemplate?
ItemsControl: как использовать FindName в ItemsPanelTemplate для доступа к панели
Доступ к дочернему элементу ListBoxItem
Доступ к элементу управления из 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) });
}