WPF ListView désactiver la sélection

119

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

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

ListView

Je voudrais que la ligne 1 ressemble à la ligne 0 lorsque vous cliquez dessus.

Éventuellement lié: puis-je styliser l'apparence du survol / de la sélection? Par exemple. pour remplacer l'aspect de survol dégradé bleu (ligne 3) par une couleur unie personnalisée. J'ai trouvé ceci et cela , malheureusement sans aide.

(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 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>
Martin Konicek
la source
Je n'ai jamais utilisé de ListView dans WPF auparavant, mais je suis sûr qu'il existe une sorte de propriété IsEnabled qui, si elle était définie sur false, désactiverait tout le contrôle et réaliserait probablement ce que vous recherchez, mais je suis pas sûr à 100%.
James McConnell
Salut, oui, il existe une propriété IsEnabled, qui peut désactiver l'ensemble de ListView. J'ai besoin que ListView fonctionne normalement, mais n'affichez pas la sélection.
Martin Konicek

Réponses:

135

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>

Cependant, si vous avez toujours besoin de la fonctionnalité de ListView, comme la possibilité de 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 plusieurs façons, de la modification du ControlTemplate de ListViewItem à la définition d'un style (beaucoup plus facile). Vous pouvez créer un style pour les 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>

De plus, à moins que vous n'ayez un autre moyen d'avertir l'utilisateur lorsque l'élément est sélectionné (ou juste pour le 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}" />
rmoore
la source
2
Vous n'avez pas vu la partie associée, mais vous pouvez faire la même chose, en définissant l'arrière-plan et la bordure comme vous le souhaitez sur la propriété IsMouseOver.
rmoore le
88
Je l'ai encore mieux résolu maintenant - <Setter Property = "Focusable" Value = "false" /> désactive complètement la sélection de la ligne.
Martin Konicek le
8
Ahh, je pensais que vous vouliez simplement désactiver la sélection visuellement. Si vous ne voulez pas du tout qu'ils soient sélectionnés, vous voudrez peut-être jeter un oeil à l'utilisation d'un ItemsControl (puisque vous pouvez toujours définir les éléments sélectionnés via le code s'ils ne sont pas focalisables), mais pour obtenir l'apparence de la grille, vous Vous devrez faire quelque chose comme ceci: manicprogrammer.com/cs/blogs/... Aussi, si vous ne l'avez pas encore fait, vous voudrez peut-être consulter le livre WPF Unleashed, car il fournit une excellente introduction à WPF & XAML.
rmoore le
2
@MartinKonicek je sais que c'est un vieux post, mais votre commentaire le mieux noté devrait être une réponse;)
WiiMaxx
1
@MartinKonicek J'ai dû ajouter BasedOn="{StaticResource {x:Type ListViewItem}}"pour ne pas remplacer le reste de mes styles de grille, mais je pense aussi que vous devriez faire de votre commentaire la réponse acceptée
JumpingJezza
31

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 des éléments dans une zone de liste

explique pourquoi cela ne peut pas fonctionner.

Si votre liste contient uniquement 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 la vue de liste contiennent des contrôles tels que des comboboxes, car cela change également leur couleur. 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>
Mark Markindale
la source
14
Cela fait disparaître tous mes articles de ma ListView
Chuck Savage
18

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>
Hayley Guillou
la source
4
Simple et efficace. Et il fait en fait ce qui est demandé: il désactive la sélection au lieu de simplement la cacher. C'est la meilleure réponse.
Fumidu
13

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 le déclencheur IsSelected et IsSelected / IsSelectionActive MultiTrigger, en ajoutant le code ci-dessous à votre style pour remplacer le modèle par défaut, et il n'y aura aucun changement visuel une fois sélectionné.

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>
Ben Wilde
la source
12

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

<Setter Property="Focusable" Value="false"/>
Martin Konicek
la source
4
@Mutex Cela fonctionne - vous devez cependant l'appliquer ListView.ItemContainerStyle!
Andreas Niedermair
8

Suite à la solution ci-dessus ... j'utiliserais un MultiTrigger pour permettre aux surlignages MouseOver de continuer à fonctionner après la sélection de sorte que le style de votre 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>
Chien rouge
la source
6

D'accord, 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ésactivez le ListViewItem, qui bousille les styles et désactive tous les contrôles enfants
  2. Supprimer de la pile de test de positionnement, c'est-à-dire que les contrôles enfants ne survolent ni ne cliquent jamais avec la souris
  3. Rendez-le non focalisable, 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 sur lequel je veux être cliquable et survolé.

Donc, ce que je veux vraiment, c'est que le ListViewItem ne soit pas du tout un ListViewItem.Ainsi, j'ai surchargé le ControlTemplate de 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>
Bradley Burnside
la source
5

L'une des propriétés de la vue de liste est IsHitTestVisible. Décochez-le.

Jacob Levertov
la source
Simple et efficace, résolvez également mon problème avec ScrollViewer enveloppé dans une vue de liste.
Brian Ng
1
J'ai un modèle de bouton dans le modèle d'élément de liste. si désélectionné, IsHitTestVisiblele bouton ne peut pas être cliqué. Il agit commeIsEnabled = false;
Luiey
1

Ceci est pour les autres qui peuvent rencontrer les exigences suivantes:

  1. Remplacez complètement l'indication visuelle de "sélectionné" (par exemple, utilisez une forme quelconque), au-delà du simple changement de la couleur de la surbrillance 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 être chargé de manipuler manuellement cette propriété sur tous les objets de modèle.
  4. Exiger que les éléments puissent être sélectionnés dans ListView
  5. Souhaite également remplacer la représentation visuelle de IsMouseOver

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

Remplacez le ControlTemplate de 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>

Il en résulte au moment de l'exécution (l'élément 'B' est sélectionné, l'élément 'D' a la souris dessus):

Apparence de ListView

BCA
la source
1

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>
Jorge Freitas
la source
0

Le code ci-dessous désactive la sélection de ligne ListViewItem et permet également d'ajouter un remplissage, une marge, 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> 
Saikat Chakraborty
la source
0

Ci-dessous le code désactiver le focus sur 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
la source