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

问题描述 投票:0回答:5

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

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

c# .net wpf silverlight listbox
5个回答
2
投票

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


0
投票

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

Point newPoint = e.GetPosition(backgroundImage);

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

if (result.VisualHit is ListBoxItem)

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

如果您需要任何指示从哪里开始,那么请给我一个喊叫。


0
投票

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

从那里很容易处理两次点击相同的项目,或按空格/输入键。两个类的40行代码,工作正常。


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事件处理程序之前取消选择所有列表框项目,从而允许切换相同的列表框项目的选择状态。


0
投票

我开始寻找一种“内置”的方式来做到这一点。当我看到没有,并注意到我不喜欢的答案时,我想我会发布我认为最好的方法。

这个答案与Bijington的答案最相似我只是在ListBox中添加了一个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" />

相关信息:

© www.soinside.com 2019 - 2024. All rights reserved.