WPF ListView отключить выделение

121

У меня есть простой WPF 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>
Мартин Коничек
источник
Я никогда раньше не использовал ListView в WPF, но я уверен, что есть какое-то свойство IsEnabled, которое, если установлено значение false, отключит весь элемент управления и, вероятно, достигнет того, что вам нужно, но я не уверен на 100%.
Джеймс МакКоннелл,
Привет, да, есть свойство IsEnabled, которое может отключить весь ListView. Мне нужно, чтобы ListView работал нормально, просто не отображайте выбор.
Мартин Коничек,

Ответы:

136

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

<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}" />
rmoore
источник
2
Не видел связанной части, но вы можете сделать то же самое, установив фон и границу по своему усмотрению в свойстве IsMouseOver.
rmoore
88
Теперь я решил это еще лучше - <Setter Property = "Focusable" Value = "false" /> полностью отключает выбор строки.
Мартин Коничек,
8
Ах, я думал, вы имели в виду просто отключить выделение визуально. Если вы вообще не хотите, чтобы они выбирались, вы можете взглянуть на использование ItemsControl (поскольку вы все равно можете установить выбранные элементы с помощью кода, если они не являются фокусируемыми), хотя, чтобы получить вид сетки, вы Придется сделать что-то вроде этого: manicprogrammer.com/cs/blogs/. Кроме того, если вы еще этого не сделали, вы можете ознакомиться с книгой WPF Unleashed, поскольку она дает отличное введение в WPF и XAML.
rmoore
2
@MartinKonicek, я знаю, что это старый пост, но ваш высокий комментарий должен быть ответом;)
WiiMaxx
1
@MartinKonicek Мне пришлось добавить, BasedOn="{StaticResource {x:Type ListViewItem}}"чтобы он не перекрывал остальные мои стили сетки, но я также думаю, что вы должны сделать свой комментарий принятым ответом
JumpingJezza
31

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

Указание цвета выделения, выравнивания содержимого и цвета фона для элементов в 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>
Марк Маркиндейл
источник
14
Это заставляет все мои элементы в моем ListView исчезать
Чак Сэвидж
18

Установите для стиля каждого ListViewItem значение false для Focusable.

<ListView ItemsSource="{Binding Test}" >
    <ListView.ItemContainerStyle>
        <Style TargetType="{x:Type ListViewItem}">
            <Setter Property="Focusable" Value="False"/>
        </Style>
    </ListView.ItemContainerStyle>
</ListView>
Хейли Гиллоу
источник
4
Просто и эффективно. И он действительно делает то, о чем просят: он отключает выделение, а не просто скрывает его. Это лучший ответ.
Fumidu
13

Вот шаблон по умолчанию для 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 и 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>
Бен Уайльд
источник
12

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

<Setter Property="Focusable" Value="false"/>
Мартин Коничек
источник
4
@Mutex Это действительно работает, но вы должны применить это ListView.ItemContainerStyle!
Андреас Нидермайр
8

В дополнение к приведенному выше решению ... я бы использовал 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>
Красная собака
источник
6

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

  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

Одно из свойств списка - IsHitTestVisible. Снимите галочку.

Яков Левертов
источник
Просто и эффективно, также решите мою проблему с помощью ScrollViewer, завернутого в список.
Брайан Нг
1
У меня есть шаблон кнопки внутри шаблона элемента списка. если отменить выбор, IsHitTestVisibleкнопку нельзя будет нажать. Это действует какIsEnabled = false;
Луи
1

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

  1. Полностью заменить визуальную индикацию «выбрано» (например, использовать какую-то форму), помимо простого изменения цвета стандартной подсветки
  2. Включите этот выбранный показатель в DataTemplate вместе с другими визуальными представлениями вашей модели, но,
  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:

<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

BCA
источник
1

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

   <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>
Хорхе Фрейтас
источник
0

Код ниже отключает выбор строки ListViewItem, а также позволяет добавлять отступы, поля и т. Д.

<ListView.ItemContainerStyle>                                                                              
   <Style TargetType="ListViewItem">                                                                                      
       <Setter Property="Template">                                                                                            
         <Setter.Value>                                                                                             
           <ControlTemplate TargetType="{x:Type ListViewItem}">                                                                                                    
              <ListViewItem Padding="0" Margin="0">                                                                                                        
                  <ContentPresenter />
              </ListViewItem>
           </ControlTemplate>                                                          
         </Setter.Value>                                                                                       
         </Setter>
      </Style>                                                                      
  </ListView.ItemContainerStyle> 
Сайкат Чакраборти
источник
0

Ниже кода отключить фокус на ListViewItem

<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
    <Setter Property="Background" Value="Transparent" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ListViewItem}">
                <ContentPresenter />
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

mincasoft
источник