Изменить шаблон данных WPF для элемента ListBox, если он выбран - PullRequest
88 голосов
/ 28 сентября 2008

Мне нужно изменить шаблон DataTemplate для элементов в ListBox в зависимости от того, выбран элемент или нет (отображая различную / более подробную информацию при выборе).

Я не получаю событие GotFocus / LostFocus для самого верхнего элемента в DataTemplate (StackPanel) при щелчке по рассматриваемому элементу ListBox (только через вкладки), и у меня нет идей.

Ответы [ 3 ]

173 голосов
/ 28 сентября 2008

Самый простой способ сделать это - предоставить шаблон для ItemContainerStyle, а НЕ для свойства ItemTemplate. В приведенном ниже коде я создаю 2 шаблона данных: один для «невыбранных» и один для «выбранных» состояний. Затем я создаю шаблон для «ItemContainerStyle», который является фактическим «ListBoxItem», который содержит элемент. Я устанавливаю «ContentTemplate» по умолчанию в состояние «Не выбрано» и затем предоставляю триггер, который заменяет шаблон, когда свойство «IsSelected» имеет значение true. (Примечание: я устанавливаю свойство ItemsSource в коде для простоты списка строк)

<Window.Resources>

<DataTemplate x:Key="ItemTemplate">
    <TextBlock Text="{Binding}" Foreground="Red" />
</DataTemplate>

<DataTemplate x:Key="SelectedTemplate">
    <TextBlock Text="{Binding}" Foreground="White" />
</DataTemplate>

<Style TargetType="{x:Type ListBoxItem}" x:Key="ContainerStyle">
    <Setter Property="ContentTemplate" Value="{StaticResource ItemTemplate}" />
    <Style.Triggers>
        <Trigger Property="IsSelected" Value="True">
            <Setter Property="ContentTemplate" Value="{StaticResource SelectedTemplate}" />
        </Trigger>
    </Style.Triggers>
</Style>

</Window.Resources>
<ListBox x:Name="lstItems" ItemContainerStyle="{StaticResource ContainerStyle}" />
7 голосов
/ 23 декабря 2014

Чтобы установить стиль, когда элемент выбран или не выбран, все, что вам нужно сделать, это извлечь родительский элемент ListBoxItem в <DataTemplate> и вызвать изменение стиля при изменении его IsSelected. Например, приведенный ниже код создаст TextBlock со значением по умолчанию Foreground color green . Теперь, если элемент выбран, шрифт станет красным , а когда мышь над ним, элемент станет желтым . Таким образом, вам не нужно указывать отдельные шаблоны данных, как это предлагается в других ответах, для каждого состояния, которое вы хотите немного изменить.

<DataTemplate x:Key="SimpleDataTemplate">
    <TextBlock Text="{Binding}">
        <TextBlock.Style>
            <Style>
                <Setter Property="TextBlock.Foreground" Value="Green"/>
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Path=IsSelected, RelativeSource={
                        RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem }}}"
                                 Value="True">
                        <Setter Property="TextBlock.Foreground" Value="Red"/>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding Path=IsMouseOver, RelativeSource={
                        RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem }}}"
                                 Value="True">
                        <Setter Property="TextBlock.Foreground" Value="Yellow"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </TextBlock.Style>
    </TextBlock>
</DataTemplate>
6 голосов
/ 29 сентября 2008

Следует также отметить, что панель стека не фокусируется, поэтому она никогда не получит фокус (установите Focusable = True, если вы / действительно / хотите сфокусироваться). Однако в таких сценариях следует помнить, что Stackpanel является child TreeViewItem, который в данном случае является ItemContainer. Как подсказывает Мика, настройка стиля предметного контейнера - это хороший подход.

Возможно, вы могли бы сделать это, используя DataTemplates и такие вещи, как датггеры, которые будут использовать расширение разметки RelativeSouce для поиска listviewitem

...