Немає ListBox.SelectionMode = “None”, чи є інший спосіб відключити вибір у списку?


189

Як відключити вибір у ListBox?


1
Чи можете ви навести приклад того, коли дійсно мати ListBox, який ви не можете вибрати? Оскільки основна поведінка полягає у виборі предметів. Я, мабуть, вибрав би інший спосіб його відображення. (Це я не намагаюся бути критиком, а скоріше
щиро

3
@Martin: наприклад, якщо ви хочете перетягнути вміст з listboxitem - у цьому випадку ви, мабуть, не зацікавлені у виборі цього елемента. ТАКОЖ: при перетягуванні елементу: обраний пункт змін ListBox при перетягуванні в ListBox - побачити цей пост stackoverflow.com/questions/7589142 / ...
Danield

1
Я вважаю, що причина, згідно з якою Шиммі хоче використовувати ListBox, полягає в тому, що хтось, хто ставить запитання, може колись зробити список списку. Питання також для мене цінне. Скажімо, ви будуєте гру з гральною карткою. Ви можете вибрати одну карту зі своїх карток, іноді ви можете вибрати декілька, а в інший час не можете вибрати жодну.
Gqqnbig

1
Крім того, іноді у вас є 10 карток, і лише 4 з них можна вибрати. Серед чотирьох можна вибрати до 3.
Gqqnbig

1
@Marthin: Коли у вас є GridView у ListBox. Заголовки Gridview забезпечують безліч функцій, які недоступні в інших місцях. І у вас є елементи редагування в клітинах gridview.
Робін Девіс

Відповіді:


264

Підхід 1 - ItemsControl

Якщо вам не потрібні інші аспекти ListBox, ви можете використовувати це ItemsControlзамість цього. Він розміщує елементи в ItemsPanelі не має поняття відбору.

<ItemsControl ItemsSource="{Binding MyItems}" />

За замовчуванням ItemsControlне підтримує віртуалізацію своїх дочірніх елементів. Якщо у вас багато предметів, віртуалізація може знизити використання пам'яті та покращити продуктивність, і в цьому випадку ви можете використовувати підхід 2 та створити стиль ListBoxабо додати віртуалізацію до свогоItemsControl .

Підхід 2 - Стилізація ListBox

Крім того, просто стилюйте ListBox таким чином, щоб виділення не було видно.

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

24
ні, це змінить лише візуальний ефект, а не власне селекційну поведінку
Томас Левеск

8
Моя перша пропозиція полягала в використанні ItemsControl. Ви пропустили це? :)
Дрю Ноакс

5
Перечитавши ці коментарі ще раз, я хочу зазначити, що коментар @Thomas Levesque стосується лише другого підходу, який я показую. Використання звичайного ItemsControlповністю видалить будь-яку концепцію вибору.
Дрю Ноакс

1
Рішення ItemsControl видаліть з коробки підтримку прокрутки (смуга прокрутки та миші).
MuiBienCarlota

1
+1 для підходу 1 - itemsControl. Якщо у нас є величезна сторінка, яку ми маємо прокручувати, якщо користувач наводить курсор на ListBox, він фактично вимикає MouseWheel, оскільки поле списку захоплює події MouseWheel. Це означає, що користувач засмучується, що мишоподібне колесо, яке використовується для прокрутки всієї сторінки, випадково перестане працювати, залежно від того, перебуває миша над списком списку чи ні.
Контанго

159

Я знайшов дуже просте і пряме рішення, що працює для мене, я сподіваюся, що це зробить і для вас

<ListBox ItemsSource="{Items}">
    <ListBox.ItemContainerStyle>
       <Style TargetType="{x:Type ListBoxItem}">
           <Setter Property="Focusable" Value="False"/>
       </Style>
    </ListBox.ItemContainerStyle>
</ListBox>

Я думаю, він пережив це досить добре тут: asaddurrani.wordpress.com/tag/wpf-listbox-disable-selection
Sid

3
Це прекрасно. це запобігає вибраному елементу та іншим елементам управління, як-от кнопки все ще працюють. саме те, що я шукав
Франк

1
+1 для цього підходу. Якщо у нас є величезна сторінка, яку ми маємо прокручувати, якщо користувач наводить курсор на ListBox, він фактично вимикає MouseWheel, оскільки поле списку захоплює події MouseWheel. Це означає, що користувач засмучується, що мишоподібне колесо, яке використовується для прокрутки всієї сторінки, випадково перестане працювати, залежно від того, перебуває миша над списком списку чи ні.
Контанго

Відмінно. Подібний підхід працював і для мене, коли мені потрібні кнопки на елементах, щоб не викликати вибір предмета - але тільки якщо було натиснуто іншу область елемента. Просто встановіть кнопки Focusable = "False"!
Джоні Адаміт

1
Додайте цю додаткову властивість і для видалення підсвічування курсору миші: <Setter Property="IsHitTestVisible" Value="False" />
DonBoitnott

25

Ви можете перейти на використання ItemsControlзамість ListBox. У ItemsControlпоняття відбору немає, тому відключати нічого.


2
Чарівна. Я ніколи не знав, що ви можете безпосередньо оголосити ItemsControl, я думав, що це віртуально (MustOverride), дякую !!!
Шиммі Вайцхандлер

Але чи все-таки ItemControl відображатиме мої елементи в одному рядку?
Chry Cheng

@Chry так, і, крім того, ви завжди можете встановити вручну ItemTemplate.
Шиммі Вайцхандлер

2
Це призводить до втрати занадто великої функціональності - наприклад, прокрутки.
Джефф

@Jeff ви можете загортати ItemsControl у ScrollViewer, щоб отримати прокрутку.
Вілька

12

Ще один варіант, який варто розглянути, - це відключення ListBoxItems. Це можна зробити, встановивши ItemContainerStyle, як показано на наступному фрагменті.

<ListBox ItemsSource="{Binding YourCollection}">
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <Setter Property="IsEnabled" Value="False" />
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>

Якщо ви не хочете, щоб текст був сірим, ви можете вказати відключений колір, додавши пензлик до ресурсів стилю за допомогою наступної клавіші: {x: Static SystemColors.GrayTextBrushKey}. Іншим рішенням буде замінити шаблон контролю ListBoxItem.


Простий та робочий, дякую! І це застосовно і для WP 8.1 Runtime.
Малутек

8

Це також буде спрацьовувати, якщо у мене є необхідність використовувати listbox замість itemscontrol, але я просто відображаю елементи, які не повинні бути обрані, я використовую:

<ListBox.ItemContainerStyle>
    <Style TargetType="ListBoxItem">
        <Setter Property="IsHitTestVisible" Value="False" />
    </Style>
</ListBox.ItemContainerStyle>

3

Тут досить хороших відповідей, але я шукав щось дещо інше: я хочу відбору, але просто не хочу, щоб його показували (або показували в іншому питанні).

Наведені вище рішення не працювали для мене (повністю), тому я зробив щось інше: я використав новий стиль для мого списку, який повністю переробляє шаблони:

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

Починаючи з цього, ви можете легко додати власне виділення виділення або залишити його таким, якщо ви взагалі цього не хочете.


2

Хоча відповідь @Drew Noakes - швидке рішення, у більшості випадків є дефект, який виникає при встановленні кистей x: Static.

Коли ви встановите х: статичні пензлі, як пропонується, усі контрольні елементи дітей у межах списку поля успадкують цей стиль.

Це означає, що, хоча це буде працювати для відключення виділення елемента поля списку, це може спричинити небажані ефекти для дочірнього контролю.

Наприклад, якщо у вас був ComboBox у вашому ListBoxItem, він би відключив мишу над виділенням в ComboBox.

Замість цього, розгляньте можливість встановлення VisualStates для вибраних, невибраних та подій MouseOver, як описано в рішенні, згаданому в цій потоці stackoverflow : Видаліть контрольне виділення з ListBoxItem, але не дочірнє управління .

-Фріні


2

Я пропоную ще одне рішення. Просто перекройте шаблон, ListBoxItemщоб бути не що інше ContentPresenter, як так ...

<Style TargetType="{x:Type ListBoxItem}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ListBoxItem}">
                <ContentPresenter />
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Мої причини такого підходу такі:

  1. У моєму випадку я не хочу відключати взаємодію користувачів із моїм вмістом, ListBoxItemsщоб рішення для встановлення IsEnabledне працювало для мене.

  2. Інше рішення, яке намагається перевлаштувати стиль ListBoxItem, заміняючи властивості, пов'язані з кольором, працює лише для тих випадків, коли ви впевнені, що шаблон використовує ці властивості. Це нормально для стилів за замовчуванням, але розривається зі спеціальними стилями.

  3. Рішення, які використовують ItemsControlперерви занадто багато інших речей, оскільки ItemsControlмає абсолютно інший вигляд, ніж стандартний ListBoxі не підтримує віртуалізацію, тобто вам доведеться все-таки перепланувати шаблони ItemsPanel.

Вищезазначене не змінює зовнішній вигляд за замовчуванням ListBox, не вимикає елементи в шаблонах даних для ListBox, підтримує віртуалізацію за замовчуванням і працює незалежно від будь-яких стилів, які можуть бути або не використовуватися у вашому додатку. Це принцип KISS.


1

Примітка. Це рішення не відключає вибір за допомогою навігації на клавіатурі або клацання правою кнопкою миші (тобто клавіші зі стрілками, а потім клавіша пробіл)

Усі попередні відповіді або видаляють можливість вибору повністю (без комутації в режимі виконання), або просто видаляють візуальний ефект, але не виділення.

Але що робити, якщо ви хочете мати можливість вибору та показувати вибір за кодом, а не за допомогою введення користувача? Можливо, ви хочете "заморозити" вибір користувача, не відключивши все Listbox?

Рішення полягає в тому, щоб загортати весь шаблон ItemContentTemplate у кнопку, яка не має візуального хрому. Розмір кнопки повинен дорівнювати розміру Елемента, щоб він повністю покривався. Тепер скористайтеся кнопкою IsEnabled-Properties:

Увімкніть кнопку, щоб "заморозити" стан вибору елемента. Це працює, тому що увімкнена кнопка з'їдає всі події миші, перш ніж вони з'являться до списку ListboxItem-Eventhandler. Ваш ItemDataTemplate як і раніше отримуватиме MouseEvents, оскільки це частина вмісту кнопок.

Вимкніть кнопку, щоб увімкнути зміну вибору, натиснувши кнопку.

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

дартракс


1

Можливо, вам потрібна цілком функціональність ItemsControl? Вибір не дозволяє:

<ItemsControl ItemsSource="{Binding Prop1}" ItemTemplate="{StaticResource DataItemsTemplate}" />

3
@Shimmy: Тривіальні відповіді зазвичай схожі. Тут немає дублювання, гідного будь-якого прапора. Якщо у вас є якісь питання з цього приводу, будь ласка, запитайте про Meta Stack Overflow .

0

Ви можете розмістити Textblock над своїм списком списку, це не змінить вигляд вашої програми, а також не дозволить вибрати жоден елемент.


1
Однак вам все одно потрібно буде відключити навігацію по вкладках.
Амандух

0

Просте виправлення, яке працює, наприклад, у Windows Phone, полягає у встановленні вибраного елемента на нульове:

    <ListBox SelectionChanged="ListBox_SelectionChanged">

І в коді позаду:

    private void ListBox_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
    {
        (sender as ListBox).SelectedItem = null;
    }

0

Я знайшов ідеальний спосіб.
Встановіть ListBox IsHitTestVisible на хибний, щоб користувач не міг навести мишу або прокрутити вниз або прокрутити вгору.
Capture PreviewGotKeyboardFocus e.Handled = true, щоб користувач міг вибрати предмет за клавіатурою Tab, Arrow up, Arrow down.

Таким чином перевага:

  1. Елементи ListBox Передній план не стане сірим.
  2. Фон ListBox може встановити прозорий

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>

код

private void StudentsListBox_PreviewGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
    e.Handled = true;
}

-1

Для мене найкращим рішенням є:

        <ListBox.ItemContainerStyle>
            <Style TargetType="{x:Type ListBoxItem}">
                <Setter Property="Focusable" Value="True"/>
                <Setter Property="IsHitTestVisible" Value="False" />
            </Style>
        </ListBox.ItemContainerStyle>


-3

Щоб вимкнути одну або кілька опцій у списку / спадному списку, ви можете додати атрибут "вимкнено", як показано нижче. Це заважає користувачеві вибрати цей параметр, і він отримує сіру накладку.

ListItem item = new ListItem(yourvalue, yourkey);
item.Attributes.Add("disabled","disabled");
lb1.Items.Add(item);

Тоді ви отримали високу відповідь на питання WPF з рішенням ASP.NET.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.