ItemsControl: How To Use FindName within ItemsPanelTemplate to access Panel
Accessing child of ListBoxItem
Access a control from within a DataTemplate with its identifying name
我需要编写一个自定义控件来获取T列表,并在ListBox
中显示该列表的两个属性。要显示的列表属性的名称将是我的控件的属性。
Baiscally我需要重现ComboBox
的功能,复制其ItemsSource
,DisplaymemberPath
和SelectedValuePath
属性。我需要在DisplayMemberPath
控件中显示由SelectedValuePath
和ListBox
指定的属性。
由于与此帖无关的原因,我无法重新审核ComboBox
。由于我无法访问DataTemplate
内的控件(如here所述)。
我的问题是:如何在PART_ListIDTextBlock
和PART_ListDescTextBlock
上设置绑定以指向ItemsSource
上的相关属性?
同样,此处的代码不是work。
请注意,我不是在询问如何在DataTemplate
中找到控件。基于这样的答案:
Access Elements inside a DataTemplate... How to for more than 1 DataTemplate?
我认为FindName
......可能是一种错误的方法,所以我要问一个更普遍的问题,可能涉及一个完全不同的模板供我控制。
当然如果FindName
。我想知道如何做到这一点是正确的方法,因为在StackOverflow上有许多类似性质的问题,我找不到一个有答案我可以弄清楚如何使用。
<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) });
}