Лучший способ изменить выбор ListBox, чтобы быть выбором переключения - PullRequest
0 голосов
/ 19 ноября 2008

У меня есть элемент управления ListBox, который я хочу изменить, выбрав переключатель. т.е. один раз нажмите на элемент, который выделит его, нажмите еще раз, чтобы отменить его. Кроме того, если щелкнуть другой элемент в списке, по умолчанию необходимо отменить выбор предыдущего элемента и выбрать новый.

Какой лучший способ добиться этого?

Ответы [ 5 ]

2 голосов
/ 19 ноября 2008

То, что вы хотите, это RadioButtonList. Вы можете создать его, создав ItemDataTemplate и поместив в него RadioButton. Затем вы можете изменить шаблон RadioButton, чтобы он выглядел как кнопка.

0 голосов
/ 11 сентября 2018

Я отправился на поиски «встроенного» способа сделать это. Когда я увидел, что их нет, и заметил здесь ответы, которые мне не очень понравились, я решил опубликовать то, что, по моему мнению, лучший способ сделать это.

Этот ответ наиболее похож на Bijington Я просто добавил обработчик PreviewMouseDown в ListBox

<ListBox ... PreviewMouseLeftButtonDown="ListBox_OnPreviewMouseLeftButtonDown"... />

Тогда в коде

private void ListBox_OnPreviewMouseLeftButtonDown (object sender, MouseButtonEventArgs e)
{
    // I have a special extension for GetParent, numerous examples on the internet of how you would do that
    var lbi = ((DependencyObject) e.OriginalSource).GetParent<ListBoxItem>();
    if (lbi != null && lbi.IsSelected)
    {
        lbi.IsSelected = false;
        e.Handled = true;
    }
}

Тогда я подумал, что было бы неплохо превратить это в присоединенное свойство, что можно легко сделать так ...

public static class ListBoxEx
{
    private static DependencyProperty ToggleSelectionProperty = ...
    private static bool GetToggleSelection (ListBox obj) { ... }
    private static void SetToggleSelection (ListBox obj, bool shouldToggle)
    {
        obj.SetValue(ToggleSelectionProperty, shouldToggle);
        if (shouldToggle)
        {
            obj.PreviewMouseLeftButtonDown += ToggleListBox_OnPreviewMouseLeftButtonDown ;
        }
        else
        {
            obj.PreviewMouseLeftButtonDown -= ToggleListBox_OnPreviewMouseLeftButtonDown ;
        }
    }

    private static void ToggleListBox_OnPreviewMouseLeftButtonDown (object sender, MouseButtonEventArgs e)
    {
        // I have a special extension for GetParent, numerous examples on the internet of how you would do that
        var lbi = ((DependencyObject) e.OriginalSource).GetParent<ListBoxItem>();
        if (lbi != null && lbi.IsSelected)
        {
            lbi.IsSelected = false;
            e.Handled = true;
        }
    }
}

Затем в коде:

<ListBox ... yourNamespace:ListBoxEx.ToggleSelection="True" />

Соответствующая информация:

0 голосов
/ 27 января 2012

На всякий случай, если кому-то интересно, я нашел другое решение, которое мне очень помогло. Я установил ListBox.SelectionMode на Multiple и обработал событие MouseDown следующим образом:

EventManager.RegisterClassHandler(typeof(ListBoxItem),
    ListBoxItem.MouseLeftButtonDownEvent,
    new RoutedEventHandler(this.HandleListBox_MouseDown));

...

void HandleListBox_MouseDown(object sender, RoutedEventArgs e)
{
    var listBoxItem = (ListBoxItem)sender;
    if (ShouldDeselectOtherListItems(listBoxItem))
    {
        listBox.SelectedIndex = -1;
    }
}

bool ShouldDeselectOtherListItems(ListBoxItem listBoxItem)
{
    return !listBoxItem.IsSelected
        && listBox.SelectedItems.Count > 0;
}

Где listBox - родительский элемент управления ListBox. Это гарантирует, что все элементы списка отключаются перед обработкой системных обработчиков событий MouseDown, что позволяет переключать состояние выбора одного и того же элемента списка.

0 голосов
/ 19 ноября 2008

Мне удалось достичь этого самостоятельно, слегка создав два пользовательских класса, ToggleListBox и ToggleListBoxItem. Есть несколько удобных переопределений (наиболее важным в ToggleListBox является тот, который создает ваш ListBoxItem).

Оттуда легко было нажимать дважды на один и тот же элемент или нажимать клавишу пробела / ввода. 40 строк кода для обоих классов и отлично работает.

0 голосов
/ 19 ноября 2008

Я бы оставил стандартный ListBox таким образом, чтобы вы сохранили желаемое поведение по умолчанию, а затем, чтобы отменить выбор элемента, вы могли бы просто обработать его в случае нажатия кнопки мыши? то есть использовать что-то вроде этого:

Point newPoint = e.GetPosition(backgroundImage);

HitTestResult result = VisualTreeHelper.HitTest(this, newPoint);

if (result.VisualHit is ListBoxItem)

Я не уверен, что это лучший способ, единственный другой способ сделать это - извлечь свой собственный ListBox из стандартного элемента управления Windows и добавить свойство зависимостей, чтобы я мог отменить выбор в стиль. Если вы хотите использовать этот подход, я не должен удалять поведение по умолчанию, которое вы хотите сохранить, я использовал этот подход, чтобы создать ListBox, который бы отображал изображение рядом с текстом.

Если вам нужны какие-либо указатели на то, с чего начать, просто дайте мне крик.

...