WPF ListView desactivar la selección

119

Tengo un ListView de WPF simple y una pregunta simple:

¿Es posible desactivar la selección, por lo que cuando el usuario hace clic en la fila, la fila no se resalta?

Vista de la lista

Me gustaría que la fila 1 se pareciera a la fila 0 cuando se hace clic en ella.

Posiblemente relacionado: ¿puedo diseñar el aspecto del desplazamiento / selección? P.ej. para reemplazar el aspecto azul degradado flotante (línea 3) con un color sólido personalizado. He encontrado esto y esto , desafortunadamente no ayudando.

(También es aceptable lograr lo mismo sin usar ListView. Me gustaría poder usar el desplazamiento lógico y la virtualización de la interfaz de usuario como lo hace ListView)

El XAML para ListView es:

<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
fuente
Nunca antes había usado un ListView en WPF, pero estoy seguro de que hay algún tipo de propiedad IsEnabled que, si se establece en falso, deshabilitaría todo el control y probablemente lograría lo que busca, pero estoy no estoy 100% seguro.
James McConnell
Hola, sí, hay una propiedad IsEnabled, que puede deshabilitar todo ListView. Sin embargo, necesito que ListView funcione normalmente, simplemente no muestre la selección.
Martin Konicek

Respuestas:

135

Según el comentario de Martin Konicek, para desactivar completamente la selección de los elementos de la manera más simple:

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

Sin embargo, si aún necesita la funcionalidad de ListView, como poder seleccionar un elemento, puede deshabilitar visualmente el estilo del elemento seleccionado de esta manera:

Puede hacer esto de varias maneras, desde cambiar la ControlTemplate de ListViewItem hasta simplemente establecer un estilo (mucho más fácil). Puede crear un estilo para ListViewItems usando ItemContainerStyle y 'apagar' el fondo y el pincel de borde cuando está seleccionado.

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

Además, a menos que tenga alguna otra forma de notificar al usuario cuando se selecciona el elemento (o solo para probar), puede agregar una columna para representar el valor:

<GridViewColumn Header="IsSelected"
                DisplayMemberBinding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListViewItem}}, Path=IsSelected}" />
rmoore
fuente
2
No vi la parte relacionada, pero puede hacer lo mismo, configurando el fondo y el borde como desee en la propiedad IsMouseOver.
rmoore
88
Lo resolví aún mejor ahora - <Setter Property = "Focusable" Value = "false" /> desactiva completamente la selección de la fila.
Martin Konicek
8
Ahh, pensé que te referías a apagar Selection visualmente. Si no desea que se seleccionen en absoluto, es posible que desee echar un vistazo al uso de ItemsControl (ya que aún puede configurar los elementos seleccionados a través del código si no se pueden enfocar), aunque para obtener el aspecto de la cuadrícula Tendré que hacer algo como esto: manicprogrammer.com/cs/blogs/… Además, si aún no lo ha hecho, es posible que desee consultar el libro WPF Unleashed, ya que proporciona una excelente introducción a WPF y XAML.
rmoore
2
@MartinKonicek sé que es una publicación antigua, pero tu comentario de alta calificación debería ser una respuesta;)
WiiMaxx
1
@MartinKonicek Tuve que agregar BasedOn="{StaticResource {x:Type ListViewItem}}"para que no anulara el resto de mis estilos de cuadrícula, pero también creo que deberías hacer que tu comentario sea la respuesta aceptada
JumpingJezza
31

La respuesta de Moore no funciona, y la página aquí:

Especificar el color de selección, la alineación del contenido y el color de fondo para los elementos de un ListBox

explica por qué no puede funcionar.

Si su vista de lista solo contiene texto básico, la forma más sencilla de resolver el problema es utilizando pinceles transparentes.

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

Esto producirá resultados no deseados si las celdas de la vista de lista contienen controles como cuadros combinados, ya que también cambia su color. Para resolver este problema, debe redefinir la plantilla del control.

  <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
fuente
14
Esto hace que todos mis elementos en mi ListView desaparezcan
Chuck Savage
18

Establezca el estilo de cada ListViewItem para que Focusable se establezca en falso.

<ListView ItemsSource="{Binding Test}" >
    <ListView.ItemContainerStyle>
        <Style TargetType="{x:Type ListViewItem}">
            <Setter Property="Focusable" Value="False"/>
        </Style>
    </ListView.ItemContainerStyle>
</ListView>
Hayley Guillou
fuente
4
Sencillo y eficaz. Y en realidad hace lo que se le pide: desactiva la selección en lugar de simplemente ocultarla. Esta es la mejor respuesta.
Fumidu
13

Aquí está la plantilla predeterminada para ListViewItem de Blend:

Plantilla ListViewItem predeterminada:

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

Simplemente elimine IsSelected Trigger y IsSelected / IsSelectionActive MultiTrigger, agregando el siguiente código a su Estilo para reemplazar la plantilla predeterminada, y no habrá ningún cambio visual cuando se seleccione.

Solución para desactivar los cambios visuales de la propiedad 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
fuente
12

La forma más fácil que encontré:

<Setter Property="Focusable" Value="false"/>
Martin Konicek
fuente
4
@Mutex Funciona, ListView.ItemContainerStyle¡aunque tienes que aplicarlo !
Andreas Niedermair
8

Además de la solución anterior ... usaría un MultiTrigger para permitir que los aspectos destacados de MouseOver continúen funcionando después de la selección, de modo que el estilo de ListViewItem sea:

        <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>
Perro rojo
fuente
6

De acuerdo, un poco tarde para el juego, pero ninguna de estas soluciones hizo lo que estaba tratando de hacer. Estas soluciones tienen un par de problemas.

  1. Deshabilite ListViewItem, que estropea los estilos y deshabilita todos los controles secundarios
  2. Eliminar de la pila de pruebas de posicionamiento, es decir, los controles para niños nunca obtienen un mouse o clic
  3. ¿Hacer que no se pueda enfocar, esto simplemente no funcionó para mí?

Quería un ListView con los encabezados de agrupación, y cada ListViewItem debería ser simplemente 'informativo' sin selección ni pasar el cursor, pero el ListViewItem tiene un botón en el que quiero que se pueda hacer clic y que se pueda desplazar.

Entonces, realmente lo que quiero es que ListViewItem no sea un ListViewItem en absoluto, entonces, me sobrepasé el ControlTemplate de ListViewItem y lo convertí en un simple 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>
Bradley Burnside
fuente
5

Una de las propiedades de la vista de lista es IsHitTestVisible. Desmarque.

Jacob Levertov
fuente
Simple y efectivo, también resuelve mi problema con ScrollViewer envuelto en una vista de lista.
Brian Ng
1
Tengo una plantilla de botón dentro de la plantilla de elemento de la vista de lista. si anula IsHitTestVisiblela selección, no se puede hacer clic en el botón. IsEnabled = false;
Actúa
1

Esto es para otras personas que pueden encontrar los siguientes requisitos:

  1. Reemplaza completamente la indicación visual de "seleccionado" (por ejemplo, usa algún tipo de forma), más allá de solo cambiar el color del resaltado estándar
  2. Incluya esta indicación seleccionada en el DataTemplate junto con las otras representaciones visuales de su modelo, pero,
  3. No quiero tener que agregar una propiedad "IsSelectedItem" a su clase de modelo y tener la carga de manipular manualmente esa propiedad en todos los objetos del modelo.
  4. Requerir que los elementos sean seleccionables en ListView
  5. También me gustaría reemplazar la representación visual de IsMouseOver

Si es como yo (usando WPF con .NET 4.5) y descubrió que las soluciones que involucran desencadenadores de estilo simplemente no funcionaron, aquí está mi solución:

Reemplace ControlTemplate de ListViewItem en un estilo:

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

..Y el 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>

Resulta en esto en tiempo de ejecución (el elemento 'B' está seleccionado, el elemento 'D' tiene el mouse sobre):

Apariencia de ListView

BCA
fuente
1

Utilice el siguiente código:

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

El código siguiente deshabilita la selección de filas ListViewItem y también permite agregar relleno, margen, 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
fuente
0

Debajo del código, deshabilite el enfoque en 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
fuente