WPF ListView вимкнути вибір


119

У мене простий список 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>

Я ніколи раніше не використовував ListView в WPF, але я впевнений, що є якась властивість IsEnabled, яка, якщо встановити значення false, вимкне весь контроль і, ймовірно, досягне того, що ви шукаєте, але я не на 100% впевнений.
Джеймс Макконнелл

Привіт, так, є властивість IsEnabled, яка може вимкнути весь ListView. Мені потрібно, щоб ListView працював нормально, хоча вибір не відображається.
Мартін Конічек

Відповіді:


135

Коментар Мартіна Конічека, щоб повністю вимкнути вибір предметів найпростішим способом:

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

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

Ви можете зробити це кількома способами, від зміни ListViewItem в ControlTemplate просто настройки стилю (набагато простіше). Ви можете створити стиль для 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}" />

2
Не бачили пов’язаної частини, але ви можете зробити те саме, встановивши фон та межу, як вам подобається у властивості IsMouseOver.
rmoore

88
Я вирішив це ще краще - <Setter Properties = "Focusable" Value = "false" /> повністю вимикає вибір рядка.
Мартін Конічек

8
Ах, я думав, ти мав на увазі просто відключити Вибір візуально. Якщо ви взагалі не хочете, щоб їх було обрано, ви можете поглянути за допомогою пункту «Контроль» (оскільки ви все ще можете встановити вибрані елементи за допомогою коду, якщо вони не фокусуються), хоч, щоб отримати вигляд Grid Вам доведеться зробити щось на кшталт цього: 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, щоб Focusable було встановлено як false.

<ListView ItemsSource="{Binding Test}" >
    <ListView.ItemContainerStyle>
        <Style TargetType="{x:Type ListViewItem}">
            <Setter Property="Focusable" Value="False"/>
        </Style>
    </ListView.ItemContainerStyle>
</ListView>

4
Простий та ефективний. І він насправді робить те, що задається: вимикає вибір, а не просто приховує його. Це найкраща відповідь.
Фуміду

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 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

Надалі вище рішення ... Я б використав 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. Включіть цю вибрану вказівку до шаблону даних разом з іншими візуальними зображеннями вашої моделі, але,
  3. Не хочеться додавати властивість "IsSelectedItem" до свого модельного класу та бути обтяженим ручним маніпулюванням цим властивістю на всіх об'єктах моделі.
  4. Потрібно вибрати елементи в ListView
  5. Також хочеться замінити візуальне представлення IsMouseOver

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

Замініть контрольну таблицю 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 зовнішній вигляд


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>

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.