web-dev-qa-db-fra.com

WPF ListView désactive la sélection

J'ai un simple WPView ListView et une simple question:

Est-il possible de désactiver la sélection, ainsi lorsque l'utilisateur clique sur une ligne, celle-ci n'est pas mise en surbrillance?

ListView

Je voudrais que la rangée 1 ressemble à la rangée 0 lorsqu'on clique dessus.

Peut-être lié: puis-je personnaliser l'apparence du survol/de la sélection? Par exemple. pour remplacer le survol dégradé bleu (ligne 3) par une couleur unie personnalisée. J'ai trouvé ceci et ceci , malheureusement, cela n'aide pas.

(Obtenir la même chose sans utiliser ListView est également acceptable. J'aimerais simplement pouvoir utiliser le défilement logique et la virtualisation de l'interface utilisateur comme le fait ListView)

Le code XAML pour ListView est:

<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>
102
Martin Konicek

Selon le commentaire de Martin Konicek, pour désactiver complètement la sélection des éléments de la manière la plus simple:

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

Toutefois, si vous avez toujours besoin des fonctionnalités de ListView, comme pouvoir sélectionner un élément, vous pouvez désactiver visuellement le style de l'élément sélectionné, comme suit:

Vous pouvez le faire de différentes façons, en modifiant le ControlTemplate de ListViewItem en définissant simplement un style (beaucoup plus facile). Vous pouvez créer un style pour ListViewItems à l'aide de ItemContainerStyle et «désactiver» le pinceau d'arrière-plan et de bordure lorsqu'il est sélectionné.

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

En outre, à moins que vous ne disposiez d'un autre moyen d'avertir l'utilisateur lorsque l'élément est sélectionné (ou uniquement à des fins de test), vous pouvez ajouter une colonne pour représenter la valeur:

<GridViewColumn Header="IsSelected"
                DisplayMemberBinding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListViewItem}}, Path=IsSelected}" />
120
rmoore

La réponse de Moore ne fonctionne pas, et la page ici:

Spécification de la couleur de sélection, de l'alignement du contenu et de la couleur d'arrière-plan pour les éléments d'un ListBox

explique pourquoi cela ne fonctionne pas.

Si votre liste ne contient que du texte de base, le moyen le plus simple de résoudre le problème consiste à utiliser des pinceaux transparents.

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

Cela produira des résultats indésirables si les cellules de listview contiennent des contrôles tels que des listes déroulantes, car leur couleur change également. Pour résoudre ce problème, vous devez redéfinir le modèle du contrôle.

  <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>
31
Mark Markindale

Définissez le style de chaque ListViewItem pour que Focusable soit défini sur false.

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

Voici le modèle par défaut pour ListViewItem de Blend:

Modèle ListViewItem par défaut:

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

Supprimez simplement les déclencheurs IsSelected et IsSelected/IsSelectionActive MultiTrigger en ajoutant le code ci-dessous à votre style pour remplacer le modèle par défaut. Aucune modification visuelle ne sera apportée une fois sélectionnée. 

Solution pour désactiver les modifications visuelles de la propriété 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
Ben Wilde

Le moyen le plus simple que j'ai trouvé:

<Setter Property="Focusable" Value="false"/>
11
Martin Konicek

En plus de la solution ci-dessus ... J'utiliserais un MultiTrigger pour permettre aux traits saillants de MouseOver de continuer à fonctionner après la sélection, de sorte que votre style ListViewItem soit:

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

Ok, peu de retard dans le jeu, mais aucune de ces solutions n’a vraiment fait ce que j’essayais de faire ... Ces solutions ont quelques problèmes

  1. Désactiver le ListViewItem, qui visse les styles et désactive tous les contrôles enfants
  2. Supprimer de la pile de tests, par exemple, les contrôles enfants ne passent jamais la souris sur
  3. Ne le mettez pas au point, cela n'a tout simplement pas fonctionné pour moi?

Je voulais un ListView avec les en-têtes de regroupement, et chaque ListViewItem devrait simplement être «informatif» sans sélection ni survol, mais le ListViewItem contient un bouton dans lequel je souhaite être cliqué et survolé.

Donc, ce que je veux vraiment, c’est que ListViewItem ne soit pas du tout un ListViewItem, j’ai donc surchargé le ControlTemplate du ListViewItem et en ai simplement fait un ContentControl simple. 

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

Une des propriétés de la liste est IsHitTestVisible. Décochez-la.

5
Jacob Levertov

Utilisez le code ci-dessous:

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

Ceci est destiné aux autres personnes susceptibles de rencontrer les conditions suivantes:

  1. Remplacez complètement l'indication visuelle "sélectionné" (par exemple, utilisez une forme quelconque), au-delà du simple changement de couleur du surlignage standard
  2. Incluez cette indication sélectionnée dans le DataTemplate avec les autres représentations visuelles de votre modèle, mais,
  3. Vous ne voulez pas avoir à ajouter une propriété "IsSelectedItem" à votre classe de modèle et à vous charger de la manipuler manuellement sur tous les objets du modèle. 
  4. Exiger que les éléments soient sélectionnables dans ListView
  5. J'aimerais également remplacer la représentation visuelle de IsMouseOver

Si vous êtes comme moi (avec WPF avec .NET 4.5) et que les solutions impliquant des déclencheurs de style ne fonctionnent tout simplement pas, voici ma solution:

Remplacez le ControlTemplate du ListViewItem dans un style:

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

..Et le 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>

Résultats dans ceci au moment de l'exécution (l'élément 'B' est sélectionné, l'élément 'D' est survolé de la souris):

 ListView appearance

1
BCA

Le code ci-dessous désactive la sélection de lignes ListViewItem et permet également d'ajouter du remplissage, des marges, etc. 

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