防止取消选择列表框中最后一个选定项的最佳方式
本文关键字:方式 最佳 最后一个 取消 选择 列表 | 更新日期: 2023-09-27 18:19:45
我需要在wpf中为ListBox控件实现自定义行为。其想法是禁用取消选择最后一个选定的元素。根据默认行为,当用户用鼠标点击所选项目时,按住ctrl键,选择将消失。我需要实现一些逻辑,当用户在最后一个选择的项目上点击鼠标+ctrl时,使列表框什么都不做。
我找到的唯一方法是订阅ListBox.SelectionChanged并执行以下操作:
private static void listBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var listBox = sender as ListBox;
if (listBox != null && e.RemovedItems != null && e.RemovedItems.Count == 1)
{
var removed = e.RemovedItems[0];
if (listBox.SelectedItems.Count == 0)
{
if (listBox.SelectionMode == System.Windows.Controls.SelectionMode.Single)
{
listBox.SelectedItem = removed;
}
else
{
listBox.SelectedItems.Add(removed);
}
e.Handled = true;
}
}
}
但这种解决方案不适合我,因为在这种情况下,当ListBox.SelectedItem绑定到viewmodel属性时,会发生一些不需要的调用。
伪调用堆栈(取消选择所选项目时):
SelectedItem更改为空
listBox_SelectionChanged称为
SelectedItem设置为以前的值
我只希望第1步和第3步永远不会发生。这一点很重要,因为当SelectedItem更改时,会启动一些长时间运行的异步操作。
谢谢,如有任何建议,不胜感激!
找到解决方案。处理ListBox上的PreviewMouseLeftButtonDown对我来说很好。作为附加属性。
BTW:我能以某种方式解决这个问题吗?
public static class ListBoxAttachedProperties
{
public static readonly DependencyProperty DisableUnselectLast =
DependencyProperty.RegisterAttached(
"DisableUnselectLast", typeof(bool), typeof(ListBox),
new PropertyMetadata(false, DisableUnselectLastChangedCallback));
public static bool GetDisableUnselectLast(DependencyObject d)
{
return (bool)d.GetValue(DisableUnselectLast);
}
public static void SetDisableUnselectLast(DependencyObject d, bool value)
{
d.SetValue(DisableUnselectLast, value);
}
private static void DisableUnselectLastChangedCallback(
DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!(d is ListBox))
{
return;
}
var selector = d as ListBox;
bool oldValue = (bool)e.OldValue;
bool newValue = (bool)e.NewValue;
if (oldValue == newValue)
{
return;
}
if (oldValue == false)
{
selector.PreviewMouseLeftButtonDown += listBox_PreviewMouseLeftButtonDown;
}
else
{
selector.PreviewMouseLeftButtonDown -= listBox_PreviewMouseLeftButtonDown;
}
}
private static void listBox_PreviewMouseLeftButtonDown(
object sender, System.Windows.Input.MouseButtonEventArgs e)
{
var listBox = sender as ListBox;
if (listBox != null && listBox.SelectedItems.Count == 1)
{
UIElement container = listBox.ItemContainerGenerator
.ContainerFromItem(listBox.SelectedItems[0]) as UIElement;
if (container != null)
{
var pos = e.GetPosition(container);
var result = VisualTreeHelper.HitTest(container, pos);
if (result != null)
{
e.Handled = true;
}
}
}
}
}