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