【问题标题】:MouseEnter/MouseLeave and mouse left button downMouseEnter/MouseLeave 和鼠标左键按下
【发布时间】:2011-06-17 05:59:35
【问题描述】:

我正在尝试像 Windows 资源管理器中那样实现单击和拖动选择(当您按住鼠标按钮并移动鼠标时出现的蓝色选择矩形)。

所以基本上我有一个 ListView,带有样式化和模板化的 ListViewItem。 我在我的 ListViewItem 上添加了 MouseEnter 和 MouseLeave 事件(使用 EventSetter), 它工作正常,除非鼠标左键按下。 在这种情况下,事件不会被触发,这对我想要实现的目标不利。

你知道是否有任何好的解决方法吗?我想知道当鼠标左键按下时我是否在一个项目上。

目前我已经尝试过使用 VisualTreeHelper.HitTest(),但我只知道何时越过 ListViewItem,我需要知道何时离开它。

谢谢。

【问题讨论】:

    标签: c# wpf events multipleselection


    【解决方案1】:

    您必须在按下按钮时捕获鼠标 UIElement.CaptureMouse,然后在 MouseUp 事件期间释放鼠标 UIElement.ReleaseMouseCapture。您不必担心任何其他事件,因为在捕获期间所有鼠标输入都会发送到您的 UIElement。

    这种选择形式称为“套索选择”,Windows 应用程序中的大多数小部件都支持它。事实上,ListView 本身已经这样做了。

    【讨论】:

    • 好的,但我还是不明白,因为我在列表视图中捕获了鼠标(并释放它),我怎样才能获得关于哪个项目移动的信息?我没有项目事件,我不知道有什么方法可以检查鼠标是否在 ListViewItem 的范围内(除了我已经在使用 VisualTreeHelper.HitTest())
    • @StrAbZ:Google 为您搜索:manfredlange.blogspot.com/2009/04/…
    • 谢谢,这似乎完成了部分工作。它适用于鼠标指针,我仍然需要找出如何检测哪些项目在我的选择区域下,而不仅仅是鼠标指针。
    • 浏览ListView.Items 并使用他们的视觉效果来测试您的矩形。
    • 这篇文章解释了如何对几何对象(可能是一个矩形)进行命中测试:msdn.microsoft.com/en-us/library/ms748343.aspx
    【解决方案2】:

    即使您的 MouseEnter 和 Leave 事件被触发,也不会提供一个好的选择方法,因为这两个事件最终都无关紧要:您的鼠标是否接触过该文件夹或文件并不重要,重要的是它是否是在您释放按钮的时间点的矩形中。这意味着 Mouse Up & Down 应该足够了。根据您的列表,您甚至可以通过查看发生这些事件的两个项目来推断应该选择哪些项目(例如,如果它只是一个一维列表而不是二维网格)。

    如果您有一个网格,您将需要更复杂的机制,例如跟踪哪些区域被覆盖并检查哪些项目在内部或边缘。

    【讨论】:

    • 这种方法的问题是我的项目只有在用户释放鼠标按钮时才会被选中,在我的情况下,我想更接近 Windows 资源管理器的行为,这意味着当鼠标选择/取消选择项目时/“蓝色选择矩形”在一个项目上。如果我在完成工作后进行选择,但外观和 UX 体验不会像预期的那么好,我想尽可能地保持与 windows 默认行为的一致性。
    • 然后您可以在ListView 上处理MouseMove,测试相应的鼠标按钮是否按下并检查Mouse.DirectlyOver 是否返回ListViewItem。如果是这样,您可以选择它和/或取消选择鼠标最后停留的项目。有点复杂,但只是一点点逻辑交互。
    • 我可以让鼠标 IsDirectlyOver,在每个项目上进行测试,但这需要删除 MouseCapture,这是我不想要的。除非我错过了什么。
    【解决方案3】:

    所以我找到了一种不同的解决方案来处理这种行为。

    我已经开始使用这个 stackoverflow 答案Click and drag selection box in WPF

    在 mouseMove 中,修改 selectionBox 大小后,我选择了 selectionBox 区域中的项目。

    我是这样做的:

     //Select all visible items in select region.
     Rect selectRect = new Rect(Canvas.GetLeft(selectionBox), Canvas.GetTop(selectionBox),
                    (Canvas.GetLeft(selectionBox) + selectionBox.Width), (Canvas.GetTop(selectionBox) + selectionBox.Height));
    
     RectangleGeometry rr = new RectangleGeometry(selectRect);
     foreach (CustomElement elt in mainList.Items)
     {
      ListViewItem item = mainList.ItemContainerGenerator.ContainerFromItem(elt) as ListViewItem;
      Rect r = LayoutInformation.GetLayoutSlot(item);
      if (r.IntersectsWith(selectRect))
            item.IsSelected = true;
      else
            item.IsSelected = false;
     }
    

    我发现 LayoutInformation 可以为您提供代表对象的 Rect,因此我可以检查它是否与 selectionBox Rect 相交。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-04-26
      • 2014-06-14
      • 2011-02-28
      • 2023-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多