如何在DataTemplate中的控件上设置绑定?

时间:2013-02-08 21:11:48

标签: c# wpf listbox datatemplate findname

ItemsControl: How To Use FindName within ItemsPanelTemplate to access Panel

Accessing child of ListBoxItem

FindName MSDN

Access a control from within a DataTemplate with its identifying name

我需要编写一个自定义控件来获取T列表,并在ListBox中显示该列表的两个属性。要显示的列表属性的名称将是我的控件的属性。

Baiscally我需要重现ComboBox的功能,复制其ItemsSourceDisplaymemberPathSelectedValuePath属性。我需要在DisplayMemberPath控件中显示由SelectedValuePathListBox指定的属性。

由于与此帖无关的原因,我无法重新审核ComboBox。由于我无法访问DataTemplate内的控件(如here所述)。

我的问题是:如何在PART_ListIDTextBlockPART_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) });
    }

0 个答案:

没有答案