将ListBox选择更改为切换选择的最佳方法

时间:2008-11-19 10:30:20

标签: c# .net wpf silverlight listbox

我有一个ListBox控件,我想更改为具有切换选择。即,单击一个项目选择它,再次单击它取消选择它。此外,单击列表中的其他项应执行取消选择上一项并选择新项的默认操作。

实现这一目标的最佳方式是什么?

5 个答案:

答案 0 :(得分:2)

你想要的是RadioButtonList。您可以通过创建ItemDataTemplate并在其中放置RadioButton来创建一个。然后,您可以将RadioButton的模板修改为看起来像一个按钮。

答案 1 :(得分:0)

我会保持标准的ListBox,你将保持你想要的默认行为,然后取消选择一个项目你可以在鼠标按下事件中处理它吗?即使用这样的东西:

Point newPoint = e.GetPosition(backgroundImage);

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

if (result.VisualHit is ListBoxItem)

我不确定这是否是最好的方法,我要做的唯一其他方法是从标准的Windows控件派生我自己的ListBox并添加一个依赖属性以允许我处理取消选择风格。如果你想采用这种方法,我不应该删除你想要保留的默认行为,我使用这种方法创建一个ListBox,它将在文本旁边显示一个图像。

如果你需要任何关于从哪里开始的指示,那就给我一个大喊。

答案 2 :(得分:0)

我已经设法通过稍微创建两个自定义类来实现这一目标,ToggleListBox& ToggleListBoxItem。有几个方便的覆盖(ToggleListBox中最重要的是创建ListBoxItem的那个)。

从那里可以轻松地点击同一项目两次,或者按空格键/输入键。两个类的40行代码都可以正常工作。

答案 3 :(得分:0)

万一有人对此感兴趣,我找到了一个不同的解决方案,这对我很有用。我将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事件处理程序之前取消选择所有列表框项目,从而允许切换相同的列表框项目的选择状态。

答案 4 :(得分:0)

我着手寻找一种“内置”方式来做到这一点。当我看到没有答案时,发现这里不是我真正想要的答案,我想我会发布我认为最好的答案。

此答案与Bijington的答案最相似 我只是向列表框添加了一个PreviewMouseDown处理程序

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

相关信息: