Как я могу переписать ItemTemplate моего ListBox и при этом сохранить DisplayMemberPath? - PullRequest
10 голосов
/ 20 сентября 2011

У меня есть общий стиль для ListBox, который перезаписывает ItemTemplate для использования RadioButtons.Это прекрасно работает, за исключением, когда я установил DisplayMemberPath.Тогда я просто получаю .ToString() предмета в ListBox.

Мне кажется, что я упускаю что-то простое здесь ... может кто-нибудь помочь мне определить это?

<Style x:Key="RadioButtonListBoxStyle" TargetType="{x:Type ListBox}">
    <Setter Property="BorderBrush" Value="Transparent"/>
    <Setter Property="KeyboardNavigation.DirectionalNavigation" Value="Cycle" />
    <Setter Property="ItemContainerStyle">
        <Setter.Value>
            <Style TargetType="{x:Type ListBoxItem}" >
                <Setter Property="Margin" Value="2, 2, 2, 0" />
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate>
                            <Border Background="Transparent">
                                <RadioButton
                                    Content="{TemplateBinding ContentPresenter.Content}" VerticalAlignment="Center"
                                    IsChecked="{Binding Path=IsSelected,RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay}"/>

                            </Border>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </Setter.Value>
    </Setter>
</Style>

Мой ListBox связан с List<T> из KeyValuePairs,Если я удаляю Стиль, DisplayMemberPath отображается правильно, поэтому это должно быть что-то со стилем.

<ListBox Style="{StaticResource RadioButtonListBoxStyle}"
         ItemsSource="{Binding MyCollection}"
         DisplayMemberPath="Value" SelectedValuePath="Key" />

Ответы [ 4 ]

9 голосов
/ 20 сентября 2011

Почему именно вы хотите сохранить DisplayMemberPath? Это просто ярлык для ItemTemplate, содержащего TextBlock, показывающий значение в DisplayMemberPath. С вашим собственным ItemTemplate у вас гораздо больше гибкости, что и как вы хотите отобразить Просто добавьте TextBlock в ваш ItemTemplate и установите Text="{Binding Value}", и вы получите то, что хотите.

Как описано здесь

Это свойство - простой способ определить шаблон по умолчанию, который описывает, как отображать объекты данных.

DisplayMemberPath предоставляет простой способ для шаблона, но вы хотите другой. Вы не можете и вам не нужны оба.

3 голосов
/ 03 декабря 2011

Я исследую эту проблему с самого утра, и эта ветка мне очень помогла.Я исследовал решение и обнаружил, что существует способ поддержки DisplayMemberPath даже после определения пользовательского шаблона элемента управления ListboxItem в стиле.Ключ добавляет

    ContentTemplateSelector="{TemplateBinding ContentControl.ContentTemplateSelector}"

к contentpresenter (радиокнопка в случае этого потока).

Причина, по которой это будет работать, заключается в том, что внутренне свойство displaymemberpath заставляет Listbox назначать ContentTemplateSelectorв селектор шаблона «DisplayMemberTemplateSelector».Без этой привязки шаблона этот селектор не вступит в силу.

Приветствия!

3 голосов
/ 20 сентября 2011

Я до сих пор не могу понять, как заставить его рисовать, используя DisplayMemberPath, однако я нашел кусок, который мне не хватало, чтобы получить его, используя ItemTemplate - мне нужен был ContentTemplate переплет

<RadioButton 
    Content="{TemplateBinding ContentPresenter.Content}" 
    ContentTemplate="{TemplateBinding ContentPresenter.ContentTemplate}"
    IsChecked="{Binding Path=IsSelected,RelativeSource={
                        RelativeSource TemplatedParent},Mode=TwoWay}" />

Тогда в моем XAML я могу написать:

<ListBox Style="{StaticResource RadioButtonListBoxStyle}"
         ItemsSource="{Binding MyCollection}"
         SelectedValuePath="Key">

    <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Value}" />
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

Спасибо dowhilefor за то, что указал, что DisplayMemberPath - это просто сокращенный способ написания ItemTemplate, и оба не могутбыть установленным сразу.

0 голосов
/ 19 июля 2017

tl; dr

Установите ItemContainerStyle с ContentPresenter в нем, и убедитесь, что не перезаписывает ItemTemplate.

Необходимость

Вы хотите определить универсальныйстиль для повторного использования.

Вы хотите повторно использовать его с различными типами данных, чтобы иметь возможность использовать DisplayMemberPath или ItemTemplate при повторном использовании - без необходимости переопределять весь стиль.

Проблема

Вы не использовали ContentPresenter для контейнера вашего элемента.
Самому элементу некуда было бы черпать.

Решение

Для вашего конкретного случая

Поместите ContentPresenter внутри RadioButton;это должно работать:

<RadioButton IsChecked="{Binding Path=IsSelected,RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay}"
             VerticalAlignment="Center">
    <ContentPresenter />
</RadioButton>

В общем

Определить ItemContainerStyle.Это позволяет вам контролировать способ обтекания каждого элемента.

Этот стиль нацелен на ListBoxItem.

Определите шаблон этого стиля, обязательно включив ContentPresenter (где будет отображаться содержимое самого элемента).).

Пример

Определение стиля
<Style TargetType="{x:Type ListBoxItem}" x:Key="BigListBoxItemStyle" BasedOn="{StaticResource DefaultListBoxItemStyle}">
    <Setter Property="Foreground" Value="DeepPink" />
    <Setter Property="Background" Value="Transparent" />
    <Setter Property="Height" Value="71" />
    <Setter Property="FontSize" Value="18" />
    <Setter Property="BorderThickness" Value="1" />
    <Setter Property="BorderBrush" Value="Transparent" />
    <Setter Property="Padding" Value="10 5 10 5" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ListBoxItem}">
                <Border Background="{TemplateBinding Background}"
                        Margin="{TemplateBinding Margin}"
                        BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}">
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="*" />
                            <RowDefinition Height="1" />
                        </Grid.RowDefinitions>
                        <ContentPresenter Grid.Row="0" Grid.Column="0"
                                          Margin="{TemplateBinding Padding}"
                                          VerticalAlignment="Center" />
                        <Rectangle x:Name="GraySeparator"
                                   Grid.Row="1"
                                   Height="1" Stroke="Gray" Opacity="0.2"
                                   HorizontalAlignment="Stretch" VerticalAlignment="Bottom" />
                    </Grid>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsSelected" Value="True" >
                        <Setter Property="Background" Value="Yellow" />
                    </Trigger>
                    <Trigger Property="IsMouseOver" Value="True" >
                        <Setter Property="BorderBrush" Value="DarkGreen" />
                        <Setter Property="Visibility" Value="Hidden" TargetName="GraySeparator" />
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="False">
                        <Setter Property="Opacity" Value=".5" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<Style x:Key="BigListBoxStyle" TargetType="{x:Type ListBox}">
    <Setter Property="ItemContainerStyle" Value="{StaticResource BigListBoxItemStyle}" />
</Style>
Использование его
<ListBox Style="{StaticResource BigListBoxStyle}"
         ItemsSource="{Binding MyTuples}"
         DisplayMemberPath="Item2"
         SelectedItem="{Binding SelectedTuple}">
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...