Как я могу установить привязку для свойства элемента управления (которое находится внутри DataTemplate и UserControl), чтобы использовать данное свойство ItemSource?

#wpf #xaml #user-controls #datatemplate

#wpf #xaml #пользовательские элементы управления #datatemplate

Вопрос:

Я хотел бы создать UserControl, у которого есть DataTemplate, а внутри этого DataTemplate есть элементы управления. Я хотел бы привязаться к этим вложенным свойствам элементов управления (внутри DataTemplate), чтобы я мог устанавливать их при повторном использовании этого UserControl. Вложенные элементы управления будут использовать свойства ItemSource, но имена свойств свойств ItemSource могут отличаться.

UserControl:

 <UserControl x:Class="ContextMenu.BaseFilterUserControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             mc:Ignorable="d"
             x:Name="Self">
    <Grid Margin="10">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="80" />
            <ColumnDefinition Width="auto" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="70" />
        </Grid.RowDefinitions>
        <TextBlock Grid.Column="0"
                   VerticalAlignment="Center"
                   HorizontalAlignment="Right"
                   Margin="10"
                   Text="Owners" />
        <Button Grid.Column="1"
                VerticalAlignment="Center"
                HorizontalAlignment="Center"
                Margin="10"
                Click="FilteButtonClicked"
                Width="40"
                Height="40"
                x:Name="FilterButton">
            <Popup x:Name="FilterBoxPopup"
                   PlacementTarget="{Binding ElementName=FilterButton}"
                   Placement="Bottom"
                   StaysOpen="False">
                <Border BorderBrush="Black"
                        Background="White"
                        Margin="2">
                    <ListView ItemsSource="{Binding ElementName=Self, Path=FilterList}"
                              x:Name="FilterListView"
                              Height="300"
                              Width="150">
                        <ListView.ItemTemplate>
                            <DataTemplate>
                                <StackPanel Orientation="Horizontal">
                                    <!--<CheckBox IsChecked="{Binding IsChecked}" />-->
                                    <!--<TextBlock Text="{Binding Name}" />-->
                                    <!--This is where I don't know how to properly bind eg. the above control, things I tried:-->
                                    <!--<TextBlock Text="{Binding ElementName=FilterListView, Path=FilterElementName}" />-->
                                    <!--<TextBlock Text="{Binding ElementName=Self, Path=DataContext.FilterElementName}" />-->
                                    <!--<TextBlock Text="{Binding ElementName=FilterListView, Path=DataContext.FilterElementName}" />-->
                                </StackPanel>
                            </DataTemplate>
                        </ListView.ItemTemplate>
                    </ListView>
                </Border>
            </Popup>
        </Button>
        <TextBlock Grid.Column="3"
                   VerticalAlignment="Center"
                   HorizontalAlignment="Left"
                   Margin="10"
                   Text="{Binding ElementName=Self, Path=SelectedNames}" />
    </Grid>
</UserControl>

  

Это то, как используется UserControl, FilterElementName=»Name» — это то, что я хотел бы установить, в зависимости от списка, привязанного к списку FilterList:

 <local:BaseFilterUserControl FilterList="{Binding Owners}"
                             FilterElementName="Name"
                             SelectedNames="{Binding SelectedNames}"/>
  

В этом случае Owners — это простой IReadOnlyList класса Owner. Класс Owner имеет свойство string Name. Но я буду использовать этот UserControl снова с другим списком, например. где я хотел бы использовать свойство Release списка версий (для текстового блока внутри UserControl):

 <local:BaseFilterUserControl FilterList="{Binding Versions}"
                             FilterElementName="Release"
                             SelectedNames="{Binding SelectedReleases}"/>
  

ListView правильно заполнен элементами, поэтому свойство FilterList DependencyProperty работает. Но вложенные элементы управления работают только тогда, когда я жестко кодирую привязки:

 <TextBlock Text="{Binding Name}" />
  

Ответ №1:

Для этого вам нужно было бы привязать свойство Path вашей текстовой привязки TextBlocks к свойству FilterElementName вашего UserControl. К сожалению, свойство Path класса Binding не является DependencyProperty и, следовательно, не может быть привязано.

Одним из способов достижения вашей цели было бы использовать свойство DisplayMemberPath ListView, которое является привязываемым:

    <ListView x:Name="FilterListView"
              Width="150"
              Height="300"
              ItemsSource="{Binding ElementName=Self, Path=FilterList}"
              DisplayMemberPath="{Binding ElementName=self, Path=FilterElementName}"/>
  

Если этот подход не работает, потому что вам нужно указать более сложный ItemTemplate, другим способом было бы создать свойство типа DataTemplate в вашем UserControl, используйте это как ItemTemplate в ListView и укажите его извне следующим образом:

     <local:BaseFilterUserControl FilterList="{Binding Versions}"
                                 SelectedNames="{Binding SelectedReleases}">
        <local:BaseFilterUserControl.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Release}" />
            </DataTemplate>
        </local:BaseFilterUserControl.ItemTemplate>
    </local:BaseFilterUserControl>