WPF ListView отключить выбор - PullRequest
108 голосов
/ 27 июня 2009

У меня есть простой WPF ListView и простой вопрос:

Можно ли отключить выделение, чтобы, когда пользователь щелкает строку, строка не выделялась?

ListView

Я бы хотел, чтобы строка 1 при нажатии выглядела так же, как строка 0.

Возможно, связано: можно ли стилизовать вид при наведении / выделении? Например. заменить синий вид градиента при наведении курсора (строка 3) на собственный сплошной цвет. Я нашел это и это , к сожалению, не помогает.

(Достижение того же самого без использования ListView также приемлемо. Я просто хотел бы использовать логическую прокрутку и виртуализацию пользовательского интерфейса, как это делает ListView)

XAML для ListView:

<ListView Height="280" Name="listView">
    <ListView.Resources>
        <!-- attempt to override selection color -->
        <SolidColorBrush x:Key="{x:Static SystemColors.HighlightColorKey}"
                         Color="Green" />
    </ListView.Resources>
    <ListView.View>
        <GridView>
            <GridView.Columns>
                <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}" />
                <!-- more columns -->
            </GridView.Columns>
        </GridView>
     </ListView.View>
</ListView>

Ответы [ 11 ]

123 голосов
/ 27 июня 2009

За комментарий Мартина Коничека, чтобы полностью отключить выбор предметов самым простым способом:

<ListView>
    <ListView.ItemContainerStyle>
        <Style TargetType="ListViewItem">
            <Setter Property="Focusable" Value="false"/>
        </Style>
    </ListView.ItemContainerStyle>
    ...
</ListView>

Однако если вам все еще требуется функциональность ListView, например, возможность выбрать элемент, вы можете визуально отключить стилизацию выбранного элемента, например, так:

Вы можете сделать это несколькими способами, от изменения ControlTemplate элемента ListViewItem до простой установки стиля (намного проще). Вы можете создать стиль для ListViewItems, используя ItemContainerStyle и «отключить» кисть фона и границы, когда она выбрана.

<ListView>
    <ListView.ItemContainerStyle>
        <Style TargetType="{x:Type ListViewItem}">
            <Style.Triggers>
                <Trigger Property="IsSelected"
                         Value="True">
                    <Setter Property="Background"
                            Value="{x:Null}" />
                    <Setter Property="BorderBrush"
                            Value="{x:Null}" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </ListView.ItemContainerStyle>
    ...
</ListView>

Кроме того, если у вас нет другого способа уведомления пользователя, когда элемент выбран (или только для тестирования), вы можете добавить столбец для представления значения:

<GridViewColumn Header="IsSelected"
                DisplayMemberBinding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListViewItem}}, Path=IsSelected}" />
31 голосов
/ 11 июля 2010

Ответ Мура не работает, и страница здесь:

Указание цвета выделения, выравнивания содержимого и цвета фона для элементов в ListBox

объясняет, почему это не может работать.

Если ваш список содержит только основной текст, самый простой способ решить эту проблему - использовать прозрачные кисти.

<Window.Resources>
  <Style TargetType="{x:Type ListViewItem}">
    <Style.Resources>
      <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="#00000000"/>
      <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="#00000000"/>
    </Style.Resources>
  </Style>
</Window.Resources>

Это приведет к нежелательным результатам, если ячейки списка содержат элементы управления, такие как комбинированные списки, так как они также изменяют свой цвет. Чтобы решить эту проблему, вы должны переопределить шаблон элемента управления.

  <Window.Resources>
    <Style TargetType="{x:Type ListViewItem}">
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate TargetType="{x:Type ListViewItem}">
            <Border SnapsToDevicePixels="True" 
                    x:Name="Bd" 
                    Background="{TemplateBinding Background}" 
                    BorderBrush="{TemplateBinding BorderBrush}" 
                    BorderThickness="{TemplateBinding BorderThickness}" 
                    Padding="{TemplateBinding Padding}">
              <GridViewRowPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" 
                                    VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
                                    Columns="{TemplateBinding GridView.ColumnCollection}" 
                                    Content="{TemplateBinding Content}"/>
            </Border>
            <ControlTemplate.Triggers>
              <Trigger Property="IsEnabled" 
                       Value="False">
                <Setter Property="Foreground" 
                        Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
              </Trigger>
            </ControlTemplate.Triggers>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>
  </Window.Resources>
17 голосов
/ 07 ноября 2014

Установите стиль каждого ListViewItem, чтобы Focusable был установлен в false.

<ListView ItemsSource="{Binding Test}" >
    <ListView.ItemContainerStyle>
        <Style TargetType="{x:Type ListViewItem}">
            <Setter Property="Focusable" Value="False"/>
        </Style>
    </ListView.ItemContainerStyle>
</ListView>
12 голосов
/ 12 марта 2015

Самый простой способ, который я нашел:

<Setter Property="Focusable" Value="false"/>
12 голосов
/ 16 апреля 2013

Вот шаблон по умолчанию для ListViewItem из Blend:

Шаблон ListViewItem по умолчанию:

        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ListViewItem}">
                    <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
                        <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsSelected" Value="true">
                            <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
                            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/>
                        </Trigger>
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="IsSelected" Value="true"/>
                                <Condition Property="Selector.IsSelectionActive" Value="false"/>
                            </MultiTrigger.Conditions>
                            <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/>
                            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}}"/>
                        </MultiTrigger>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>

Просто удалите IsSelected Trigger и IsSelected / IsSelectionActive MultiTrigger, добавив приведенный ниже код в свой стиль, чтобы заменить шаблон по умолчанию, и визуальные изменения при выборе не будут

Решение для отключения визуальных изменений свойства IsSelected:

    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ListViewItem}">
                <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
                    <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsEnabled" Value="false">
                        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
8 голосов
/ 05 ноября 2009

В дополнение к решению, приведенному выше ... Я бы использовал MultiTrigger, чтобы позволить выделениям MouseOver продолжать работать после выбора таким образом, чтобы стиль вашего ListViewItem был:

        <ListView.ItemContainerStyle>
            <Style TargetType="ListViewItem">
                <Style.Triggers>
                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="IsSelected" Value="True" />
                            <Condition Property="IsMouseOver" Value="False" />
                        </MultiTrigger.Conditions>
                        <MultiTrigger.Setters>
                            <Setter Property="Background" Value="{x:Null}" />
                            <Setter Property="BorderBrush" Value="{x:Null}" />
                        </MultiTrigger.Setters>
                    </MultiTrigger>
                </Style.Triggers>
            </Style>
        </ListView.ItemContainerStyle>
5 голосов
/ 01 октября 2016

Ладно, немного опоздал к игре, но ни одно из этих решений не сделало то, что я пытался сделать. У этих решений есть пара проблем

  1. Отключить ListViewItem, который испортил стили и отключил все дочерние элементы управления
  2. Удалить из стека тестов на попадание, т. Е. Дочерние элементы управления никогда не наведут курсор мыши или не нажмут
  3. Сделай так, чтобы это не фокусировалось, это просто у меня не получилось?

Я хотел ListView с заголовками группировки, и каждый ListViewItem должен быть просто «информационным» без выделения или наведения на него, но в ListViewItem есть кнопка, которую я хочу сделать доступной для кликов и навести курсор мыши на нее.

Итак, на самом деле я хочу, чтобы ListViewItem вообще не был ListViewItem. Итак, я перебрал ControlTemplate объекта ListViewItem и просто сделал его простым ContentControl.

<ListView.ItemContainerStyle>
    <Style TargetType="ListViewItem">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate>
                    <ContentControl Content="{Binding Content, RelativeSource={RelativeSource TemplatedParent}}"/>
                </ControlTemplate>
            </Setter.Value>
         </Setter>
     </Style>
</ListView.ItemContainerStyle>
5 голосов
/ 06 марта 2016

Одним из свойств списка является IsHitTestVisible. Снимите флажок.

1 голос
/ 25 февраля 2018

Используйте код ниже:

   <ListView.ItemContainerStyle>
          <Style TargetType="{x:Type ListViewItem}">
           <Setter Property="Background" Value="Transparent`enter code here`" />
             <Setter Property="Template">
               <Setter.Value>
                 <ControlTemplate TargetType="{x:Type ListViewItem}">
                   <ContentPresenter />
                 </ControlTemplate>
               </Setter.Value>
             </Setter>
          </Style>
   </ListView.ItemContainerStyle>
1 голос
/ 18 мая 2017

Это для тех, кто может столкнуться со следующими требованиями:

  1. Полностью замените визуальную индикацию «выбранного» (например, используйте какую-либо форму), за исключением простого изменения цвета стандартной подсветки
  2. Включите это выбранное указание в шаблон данных вместе с другими визуальными представлениями вашей модели, но
  3. Не нужно добавлять свойство «IsSelectedItem» в класс модели и обременяться ручной манипуляцией этим свойством на всех объектах модели.
  4. Требуется, чтобы элементы выбирались в ListView
  5. Также хотел бы заменить визуальное представление IsMouseOver

Если вы похожи на меня (используете WPF с .NET 4.5) и обнаружили, что решения, включающие триггеры стилей, просто не работают, вот мое решение:

Замените ControlTemplate элемента ListViewItem в стиле:

<ListView ItemsSource="{Binding MyStrings}" ItemTemplate="{StaticResource dtStrings}">
        <ListView.ItemContainerStyle>
            <Style TargetType="ListViewItem">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="ListViewItem">
                            <ContentPresenter/>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </ListView.ItemContainerStyle>
    </ListView>

.. И шаблон данных:

<DataTemplate x:Key="dtStrings">
        <Border Background="LightCoral" Width="80" Height="24" Margin="1">
            <Grid >
                <Border Grid.ColumnSpan="2" Background="#88FF0000" Visibility="{Binding RelativeSource={RelativeSource AncestorType=ListViewItem}, Path=IsMouseOver, Converter={StaticResource conBoolToVisibilityTrueIsVisibleFalseIsCollapsed}}"/>
                <Rectangle Grid.Column="0" Fill="Lime" Width="10" HorizontalAlignment="Left" Visibility="{Binding RelativeSource={RelativeSource AncestorType=ListViewItem}, Path=IsSelected, Converter={StaticResource conBoolToVisibilityTrueIsVisibleFalseIsCollapsed}}" />
                <TextBlock Grid.Column="1" Text="{Binding}" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White" />
            </Grid>
        </Border>
    </DataTemplate>

Результат во время выполнения (выбран элемент «B», на элементе «D» наведен курсор мыши):

ListView appearance

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...