¿Cómo desactivo la selección en un ListBox?
¿Cómo desactivo la selección en un ListBox?
Respuestas:
ItemsControl
A menos que necesite otros aspectos de la ListBox
, podría utilizar ItemsControl
en su lugar. Coloca elementos en ItemsPanel
y no tiene el concepto de selección.
<ItemsControl ItemsSource="{Binding MyItems}" />
Por defecto, ItemsControl
no admite la virtualización de sus elementos secundarios. Si tiene muchos elementos, la virtualización puede reducir el uso de memoria y mejorar el rendimiento, en cuyo caso podría usar el enfoque 2 y darle estilo ListBox
, o agregar virtualización a suItemsControl
.
ListBox
Alternativamente, simplemente diseñe el ListBox de modo que la selección no sea visible.
<ListBox.Resources>
<Style TargetType="ListBoxItem">
<Style.Resources>
<!-- SelectedItem with focus -->
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}"
Color="Transparent" />
<!-- SelectedItem without focus -->
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}"
Color="Transparent" />
<!-- SelectedItem text foreground -->
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}"
Color="Black" />
</Style.Resources>
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
</Style>
</ListBox.Resources>
ItemsControl
eliminará por completo cualquier concepto de selección.
Encontré una solución muy simple y directa que funciona para mí, espero que también sirva para ti
<ListBox ItemsSource="{Items}">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Focusable" Value="False"/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
Focusable = "False"
!
<Setter Property="IsHitTestVisible" Value="False" />
Puede cambiar a usar un en ItemsControl
lugar de un ListBox
. Un ItemsControl
no tiene un concepto de selección, por lo que no hay nada que apagar.
ItemTemplate
.
Otra opción que vale la pena considerar es deshabilitar ListBoxItems. Esto se puede hacer configurando el ItemContainerStyle como se muestra en el siguiente fragmento.
<ListBox ItemsSource="{Binding YourCollection}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="IsEnabled" Value="False" />
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
Si no desea que el texto sea gris, puede especificar el color deshabilitado agregando un pincel a los recursos del estilo con la siguiente clave: {x: Static SystemColors.GrayTextBrushKey}. La otra solución sería anular la plantilla de control ListBoxItem.
Esto también funcionará, si tengo la necesidad de usar listbox en lugar de itemscontrol, pero solo estoy mostrando los elementos que no deberían ser seleccionables, uso:
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="IsHitTestVisible" Value="False" />
</Style>
</ListBox.ItemContainerStyle>
Muy buenas respuestas aquí, pero estaba buscando algo ligeramente diferente: quiero selección, pero simplemente no quiero que se muestre (o se muestre en un asunto diferente).
Las soluciones anteriores no me funcionaron (completamente), así que hice algo más: utilicé un nuevo estilo para mi cuadro de lista, que redefine completamente las plantillas:
<Style x:Key="PlainListBoxStyle" TargetType="ListBox">
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<ContentPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBox}">
<ItemsPresenter/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Comenzando con eso, puede agregar fácilmente su propio resaltado de selección, o dejarlo así si no desea ninguno.
Si bien la respuesta de @Drew Noakes es una solución rápida para la mayoría de los casos, hay un pequeño defecto que viene con la configuración de x: cepillos estáticos.
Cuando configura los pinceles x: Static como se sugiere, todos los controles secundarios dentro del elemento del cuadro de lista heredarán este estilo.
Eso significa que, si bien esto funcionará para deshabilitar el resaltado del elemento del cuadro de lista, puede provocar efectos no deseados para los controles secundarios.
Por ejemplo, si tuviera un ComboBox dentro de su ListBoxItem, deshabilitaría el mouse sobre el resaltado dentro del ComboBox.
En su lugar, considere configurar VisualStates para los eventos Selected, Unselected y MouseOver como se cubre en la solución mencionada en este hilo de stackoverflow: Eliminar Control Highlight From ListBoxItem pero no los controles secundarios .
-Frinny
Propongo otra solución más. Simplemente cambie la plantilla ListBoxItem
para que no sea más que un ContentPresenter
, así ...
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<ContentPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Mis razones para este enfoque son las siguientes:
En mi caso, no quiero deshabilitar la interacción del usuario con el contenido de mi, ListBoxItems
por lo que la solución para configurar IsEnabled
no funcionará para mí.
La otra solución que intenta cambiar el estilo ListBoxItem
anulando las propiedades relacionadas con el color solo funciona para aquellas instancias en las que está seguro de que la plantilla usa esas propiedades. Eso está bien para los estilos predeterminados, pero rompe con los estilos personalizados.
Las soluciones que usan un sistema ItemsControl
rompen demasiadas cosas, ya que ItemsControl
tienen un aspecto completamente diferente al estándar ListBox
y no admiten la virtualización, lo que significa que de ItemsPanel
todos modos tiene que volver a crear la plantilla .
Lo anterior no cambia el aspecto predeterminado del ListBox
, no deshabilita los elementos en las plantillas de datos para ListBox
, admite la virtualización de forma predeterminada y funciona independientemente de los estilos que pueden o no estar en uso en su aplicación. Es el principio KISS.
Nota: Esta solución no deshabilita la selección mediante la navegación con el teclado o haciendo clic derecho (es decir, las teclas de flecha seguidas de la barra espaciadora)
Todas las respuestas anteriores eliminan la selección de habilidad por completo (sin cambiar en tiempo de ejecución) o simplemente eliminan el efecto visual, pero no la selección.
Pero, ¿qué sucede si desea poder seleccionar y mostrar la selección por código, pero no por entrada del usuario? ¿Es posible que desee "congelar" la selección del usuario sin deshabilitar todo el cuadro de lista?
La solución es envolver todo el ItemContentTemplate en un botón que no tiene cromo visual. El tamaño del botón debe ser igual al tamaño del artículo, por lo que está completamente cubierto. Ahora use la propiedad IsEnabled-button del botón:
Habilite el botón para "congelar" el estado de selección del elemento. Esto funciona porque el botón habilitado come todos los eventos del mouse antes de que aparezcan en el ListboxItem-Eventhandler. Your ItemsDataTemplate seguirá recibiendo MouseEvents porque es parte del contenido de los botones.
Deshabilite el botón para permitir cambiar la selección haciendo clic.
<Style x:Key="LedCT" TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Button IsEnabled="{Binding IsSelectable, Converter={StaticResource BoolOppositeConverter}}" Template="{DynamicResource InvisibleButton}">
<ContentPresenter />
</Button>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ControlTemplate x:Key="InvisibleButton" TargetType="{x:Type Button}">
<ContentPresenter/>
</ControlTemplate>
Dartrax
¿Tal vez solo necesita la funcionalidad de ItemsControl? No permite la selección:
<ItemsControl ItemsSource="{Binding Prop1}" ItemTemplate="{StaticResource DataItemsTemplate}" />
Una solución simple que funciona en Windows Phone, por ejemplo, es la selección que establece el elemento seleccionado en nulo:
<ListBox SelectionChanged="ListBox_SelectionChanged">
Y en el código detrás:
private void ListBox_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
(sender as ListBox).SelectedItem = null;
}
Encontré una manera perfecta.
Establezca ListBox IsHitTestVisible en false para que el usuario no pueda desplazar el mouse o desplazarse hacia abajo o hacia arriba.
Capture PreviewGotKeyboardFocus e.Handled = true para que el usuario pueda seleccionar el elemento con el teclado Tab, Flecha arriba, Flecha abajo.
De esta manera ventaja:
xmal
<ListBox Name="StudentsListBox" ItemsSource="{Binding Students}" ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollBarVisibility="Disabled" BorderThickness="0" Background="Transparent" IsHitTestVisible="False" PreviewGotKeyboardFocus="StudentsListBox_PreviewGotKeyboardFocus">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Padding" Value="0"/>
<Setter Property="Margin" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border x:Name="Bd">
<ContentPresenter/>
</Border>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Selector.IsSelectionActive" Value="False" />
<Condition Property="IsSelected" Value="True" />
</MultiTrigger.Conditions>
<Setter TargetName="Bd" Property="Background" Value="Yellow" />
<Setter TargetName="Bd" Property="BorderBrush" Value="Transparent" />
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Margin="0,0,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Name="GradeBlock" Text="{Binding Grade}" FontSize="12" Margin="0,0,5,0"/>
<TextBlock Grid.Column="1" Name="NameTextBlock" Text="{Binding Name}" FontSize="12" TextWrapping="Wrap"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ListBox>
código
private void StudentsListBox_PreviewGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
e.Handled = true;
}
Para mí la mejor solución es:
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Focusable" Value="True"/>
<Setter Property="IsHitTestVisible" Value="False" />
</Style>
</ListBox.ItemContainerStyle>
IsEnabled = falso
Para deshabilitar una o más opciones en su cuadro de lista / menú desplegable, puede agregar el atributo "deshabilitado" como se muestra a continuación. Esto evita que el usuario seleccione esta opción y obtiene una superposición gris.
ListItem item = new ListItem(yourvalue, yourkey);
item.Attributes.Add("disabled","disabled");
lb1.Items.Add(item);