我需要在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已更改为null
listBox_SelectionChanged被称为
SelectedItem设置为上一个值
我想要的只是步骤1和3不会发生。这很重要,因为当SelectedItem更改时,会启动一些长时间运行的异步操作。
谢谢,任何建议都将不胜感激!
答案 0 :(得分:1)
找到解决方案。在ListBox上处理PreviewMouseLeftButtonDown对我来说很好。作为附属财产。
顺便说一句:我可以以某种方式解决这个问题吗?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;
}
}
}
}
}