ListBoxItem子元素中的鼠标交互(WPF)

4

我有一个带有ItemTemplate的ListBox,其中包含一个与鼠标交互的控件。这会干扰ListBox的选择功能,即单击控件不会选择该项。这是因为ListBoxItem在OnMouseLeftButtonDown中将鼠标事件的Handled属性设置为true。我尝试了以下方法:

protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) {
    base.OnMouseLeftButtonDown(e);
    e.Handled = false;
}

但是ListBoxItem“占用”了鼠标并阻止控件进行自己的交互。然后我又有了另一个想法。
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) {
    base.OnMouseLeftButtonDown(e);
    ((ListBoxItem)VisualTreeHelper.GetParent(VisualTreeHelper.GetParent(VisualTreeHelper.GetParent(this)))).IsSelected = true;
}

目前已经有一种可行的解决方案,但是感觉更像是一个丑陋的曲线救国,而不是一个优雅的解决方案。是否有更好的解决方案,不依赖于可视树的确切内容?

3个回答

0

我找到了一种较少笨拙的方法:

protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) {
    base.OnMouseLeftButtonDown(e);
    Selector.SetIsSelected(this, true);
}

为了使其生效,ListBox中的控件需要具有以下XAML属性:
Selector.IsSelected="{Binding IsSelected, Mode=OneWayToSource, RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}}"

这引出了两个新问题:

  1. 定义自己的依赖属性是否比找到一个当前未使用的附加属性更好?
  2. 有没有一种仅通过标记实现类似功能的方法?

0

这里有一个简单的解决方案,但不幸的是处理程序只能在代码中附加,而不能在标记中附加。
可以使用AddHandler方法的handledEventsToo签名添加事件处理程序:

myListBox.AddHandler(UIElement.MouseDownEvent, 
        new MouseButtonEventHandler(ListBox_MouseDown), true);

上面的第三个参数是handledEventsToo,它确保无论是否已标记为Handled(ListBox中的ListBoxItem会这样做),都将调用此处理程序。

请参见{{link1:将路由事件标记为已处理和类处理}}以获取说明。
请参见{{link2:如何在ListBox上附加MouseDown事件}}作为示例。


0
我相信MouseLeftButtonDown是一个隧道事件:你可以尝试使用PreviewMouseLeftButtonDown,在那里进行处理,然后确保e.Handled = false;就像你已经尝试过的那样 - 那应该就可以解决问题了!
希望能有所帮助。

谢谢您的建议,但是您搞反了:MouseLeftButtonDown是冒泡事件,而PreviewMouseLeftButtonDown是隧道事件。 :) 使用PreviewMouseLeftButtonDown会如何改善情况? - absence
预览事件发生在实际事件之前:如果你在那里进行处理,然后设置 e.Handled = false;,你的代码将会被执行,但 ListBox 仍将运行其自己的处理代码,以更改所选项目。至少希望如此;那是我理解的方式! - Kieren Johnstone

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接