Изменить WPF DataTemplate для элемента списка, если он выбран


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

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

3 85

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>