WPF ListView deaktiviert die Auswahl


119

Ich habe eine einfache WPF ListView und eine einfache Frage:

Ist es möglich, die Auswahl zu deaktivieren, sodass die Zeile nicht hervorgehoben wird, wenn der Benutzer auf die Zeile klickt?

Listenansicht

Ich möchte, dass die Zeile 1 beim Klicken genauso aussieht wie die Zeile 0.

Möglicherweise verwandt: Kann ich das Aussehen des Hovers / der Auswahl stylen? Z.B. um den blauen Farbverlaufs-Hover-Look (Zeile 3) durch eine benutzerdefinierte Volltonfarbe zu ersetzen. Ich habe dies und das gefunden , leider nicht hilfreich.

(Dasselbe ohne ListView zu erreichen, ist ebenfalls akzeptabel. Ich möchte nur das logische Scrollen und die UI-Virtualisierung wie ListView verwenden können.)

Die XAML für ListView lautet:

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

Ich habe noch nie zuvor eine ListView in WPF verwendet, aber ich bin sicher, dass es eine Art IsEnabled-Eigenschaft gibt, die, wenn sie auf false gesetzt wird, das gesamte Steuerelement deaktiviert und wahrscheinlich das erreicht, wonach Sie suchen, aber ich bin es nicht 100% sicher.
James McConnell

Hallo, ja, es gibt eine IsEnabled-Eigenschaft, die die gesamte ListView deaktivieren kann. Ich brauche die ListView, um normal zu funktionieren, aber zeige die Auswahl einfach nicht an.
Martin Konicek

Antworten:


135

Per Martin Koniceks Kommentar, um die Auswahl der Elemente auf einfachste Weise vollständig zu deaktivieren:

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

Wenn Sie jedoch weiterhin die Funktionalität der ListView benötigen, z. B. die Auswahl eines Elements, können Sie das Styling des ausgewählten Elements wie folgt visuell deaktivieren:

Sie können dies eine Reihe von Möglichkeiten tun, von der der ListViewItem Wechsel Control nur einen Stil (viel einfacher) einstellen. Sie können mit dem ItemContainerStyle einen Stil für die ListViewItems erstellen und den Hintergrund und den Rahmenpinsel bei Auswahl deaktivieren .

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

Sofern Sie den Benutzer nicht auf andere Weise benachrichtigen können, wenn das Element ausgewählt ist (oder nur zum Testen), können Sie eine Spalte hinzufügen, um den Wert darzustellen:

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

2
Der zugehörige Teil wurde nicht angezeigt, aber Sie können das Gleiche tun, indem Sie den Hintergrund und den Rahmen in der IsMouseOver-Eigenschaft so einstellen, wie Sie möchten.
rmoore

88
Ich habe es jetzt noch besser gelöst - <Setter Property = "Focusable" Value = "false" /> deaktiviert die Auswahl der Zeile vollständig.
Martin Konicek

8
Ahh, ich dachte du meinst nur die Auswahl visuell ausschalten. Wenn Sie nicht möchten, dass sie überhaupt ausgewählt werden, sollten Sie einen Blick auf die Verwendung eines ItemsControl werfen (da Sie die ausgewählten Elemente weiterhin über Code festlegen können, wenn sie nicht fokussierbar sind), um das Raster-Aussehen zu erhalten Ich muss so etwas tun: manicprogrammer.com/cs/blogs/… Wenn Sie es noch nicht getan haben, können Sie auch das Buch WPF Unleashed lesen, da es eine großartige Einführung in WPF & XAML bietet.
rmoore

2
@ MartinKonicek Ich weiß, dass das ein alter Beitrag ist, aber Ihr hoch bewerteter Kommentar sollte eine Antwort sein;)
WiiMaxx

1
@ MartinKonicek Ich musste hinzufügen, BasedOn="{StaticResource {x:Type ListViewItem}}"damit es den Rest meiner Gitterstile nicht überschrieb, aber ich denke auch, dass Sie Ihren Kommentar zur akzeptierten Antwort machen sollten
JumpingJezza

31

Moores Antwort funktioniert nicht und die Seite hier:

Festlegen der Auswahlfarbe, der Inhaltsausrichtung und der Hintergrundfarbe für Elemente in einer ListBox

erklärt, warum es nicht funktionieren kann.

Wenn Ihre Listenansicht nur einfachen Text enthält, können Sie das Problem am einfachsten mit transparenten Pinseln lösen.

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

Dies führt zu unerwünschten Ergebnissen, wenn die Zellen der Listenansicht Steuerelemente wie Comboboxen enthalten, da sich auch deren Farbe ändert. Um dieses Problem zu lösen, müssen Sie die Vorlage des Steuerelements neu definieren.

  <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
Dadurch verschwinden alle meine Elemente in meiner ListView
Chuck Savage

18

Setzen Sie den Stil jedes ListViewItem so, dass Focusable auf false gesetzt ist.

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

4
Einfach und effizient. Und es macht tatsächlich das, was gefragt wird: Es schaltet die Auswahl aus, anstatt sie nur auszublenden. Dies ist die beste Antwort.
Fumidu

13

Hier ist die Standardvorlage für ListViewItem von Blend:

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

Entfernen Sie einfach den IsSelected-Trigger und den IsSelected / IsSelectionActive MultiTrigger, indem Sie den folgenden Code zu Ihrem Stil hinzufügen, um die Standardvorlage zu ersetzen. Bei Auswahl werden keine visuellen Änderungen vorgenommen.

Lösung zum Deaktivieren der visuellen Änderungen der IsSelected-Eigenschaft:

    <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

Der einfachste Weg, den ich gefunden habe:

<Setter Property="Focusable" Value="false"/>

4
@Mutex Es funktioniert - Sie müssen dies jedoch anwenden ListView.ItemContainerStyle!
Andreas Niedermair

8

Weiter zu der obigen Lösung ... Ich würde einen MultiTrigger verwenden, damit die MouseOver-Highlights nach der Auswahl weiter funktionieren, sodass der Stil Ihres ListViewItem wie folgt lautet:

        <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

Okay, etwas spät zum Spiel, aber keine dieser Lösungen hat genau das getan, was ich versucht habe. Diese Lösungen haben einige Probleme

  1. Deaktivieren Sie das ListViewItem, das die Stile durcheinander bringt und alle untergeordneten Steuerelemente deaktiviert
  2. Vom Hit-Test-Stapel entfernen, dh untergeordnete Steuerelemente erhalten niemals einen Mouse-Over oder einen Klick
  3. Machen Sie es nicht fokussierbar, das hat bei mir einfach nicht funktioniert?

Ich wollte eine ListView mit den Gruppierungsheadern, und jedes ListViewItem sollte nur 'informativ' sein, ohne Auswahl oder Mauszeiger, aber das ListViewItem enthält eine Schaltfläche, über die ich klicken und mit der Maus darüber fahren möchte.

Eigentlich möchte ich, dass das ListViewItem überhaupt kein ListViewItem ist. Also habe ich das ControlTemplate des ListViewItem überschrieben und es einfach zu einem einfachen ContentControl gemacht.

<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

Eine der Eigenschaften der Listenansicht ist IsHitTestVisible. Deaktivieren Sie es.


Einfach und effektiv, lösen Sie auch mein Problem mit ScrollViewer neben einer Listenansicht.
Brian Ng

1
Ich habe eine Schaltflächenvorlage in der Listenansicht. Wenn Sie die Auswahl IsHitTestVisibleaufheben, kann die Schaltfläche nicht angeklickt werden. Es IsEnabled = false;
verhält sich

1

Dies gilt für andere Personen, die möglicherweise die folgenden Anforderungen erfüllen:

  1. Ersetzen Sie die visuelle Anzeige "ausgewählt" vollständig (z. B. verwenden Sie eine Form), und ändern Sie nicht nur die Farbe der Standardhervorhebung
  2. Fügen Sie diese ausgewählte Anzeige zusammen mit den anderen visuellen Darstellungen Ihres Modells in die DataTemplate ein.
  3. Sie möchten Ihrer Modellklasse keine "IsSelectedItem" -Eigenschaft hinzufügen müssen und müssen diese Eigenschaft nicht manuell für alle Modellobjekte bearbeiten.
  4. Elemente müssen in der ListView auswählbar sein
  5. Möchte auch die visuelle Darstellung von IsMouseOver ersetzen

Wenn Sie wie ich (mit WPF mit .NET 4.5) sind und festgestellt haben, dass die Lösungen mit Stilauslösern einfach nicht funktionieren, ist hier meine Lösung:

Ersetzen Sie die ControlTemplate des ListViewItem in einem Stil:

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

..Und das 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>

Ergebnisse zur Laufzeit (Element 'B' ist ausgewählt, Element 'D' hat die Maus darüber):

ListView-Darstellung


1

Verwenden Sie den folgenden Code:

   <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

Der folgende Code deaktiviert die Zeilenauswahl von ListViewItem und ermöglicht das Hinzufügen von Auffüllungen, Rändern usw.

<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

Unterhalb des Codes deaktivieren Sie Focus on 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>

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.