Измените WPF DataTemplate для элемента ListBox, если он выбран
Мне нужно изменить DataTemplate для элементов в ListBox в зависимости от того, выбран ли элемент или нет (отображается различная/дополнительная информация при выборе).
Я не получаю событие GotFocus/LostFocus в самом верхнем элементе DataTemplate (StackPanel) при нажатии на элемент списка ListBox (только через tabbing), и у меня нет идей.
Ответы
Ответ 1
Самый простой способ сделать это - предоставить шаблон для свойства "ItemContainerStyle" и НЕ "ItemTemplate". В приведенном ниже коде я создаю 2 шаблона данных: один для "невыбранный" и один для "выбранных" состояний. Затем я создаю шаблон для "ItemContainerStyle", который является фактическим "ListBoxItem", который содержит элемент. Я установил значение по умолчанию "ContentTemplate" в состояние "Unselected", а затем предоставил триггер, который меняет шаблон, когда свойство IsSelected истинно. (Примечание. Я устанавливаю свойство "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}" />
Ответ 2
Следует также отметить, что стекная панель не является допустимой, поэтому она никогда не будет получать фокус (установите Focusable = True, если вы/действительно/хотите, чтобы она сфокусировалась). Тем не менее, ключ для запоминания в таких сценариях, как это, заключается в том, что Stackpanel - это дочерний TreeViewItem, который в этом случае является ItemContainer. Как утверждает Мика, тонкая настройка стиля контейнера - хороший подход.
Возможно, вы могли бы сделать это с помощью DataTemplates и таких вещей, как datatriggers, которые будут использовать расширение разметки RelativeSouce для поиска listviewitem
Ответ 3
Чтобы установить стиль, когда элемент выбран или не все, что вам нужно сделать, это восстановить родительский элемент 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>