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>
Martin Konicek
quelle
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}" />
rmoore
quelle
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>
Mark Markindale
quelle
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>
Hayley Guillou
quelle
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>
Ben Wilde
quelle
12

Der einfachste Weg, den ich gefunden habe:

<Setter Property="Focusable" Value="false"/>
Martin Konicek
quelle
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>
Roter Hund
quelle
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>
Bradley Burnside
quelle
5

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

Jacob Levertov
quelle
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

BCA
quelle
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>
Jorge Freitas
quelle
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> 
Saikat Chakraborty
quelle
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>

Mincasoft
quelle