WPF创建一个控件列表,可以通过鼠标滚动但仍保持功能

时间:2010-03-11 04:06:56

标签: c# wpf events

我有一个通过WrapPanel显示的控件列表,它是水平方向的。

我实施了“点击并拖动”滚动技术,以便用户通过点击和拖动滚动鼠标。

像这样:

<Canvas x:Name="ParentCanvas" PreviewMouseDown="Canvas_MouseDown" MouseMove="Canvas_MouseMove">
  <WrapPanel>
    <WrapPanel.RenderTransform>
      <TranslateTransform />
    </WrapPanel.RenderTransform> 

    <!-- controls are all in here ... -->
  </WrapPanel>
</Canvas>

然后在后面的代码中:

    private Point _mousePosition;
    private Point _lastMousePosition;

    private void Canvas_MouseDown(object sender, MouseButtonEventArgs e)
    {
        _lastMousePosition = e.GetPosition(ParentCanvas);
        e.Handled = true;
    }

    private void Canvas_MouseMove(object sender, MouseEventArgs e)
    {
        _mousePosition = e.GetPosition(ParentCanvas);
        var delta = _mousePosition - _lastMousePosition;

        if(e.LeftButton == MouseButtonState.Pressed && delta.X != 0)
        {
            var transform = ((TranslateTransform)_wrapPanel.RenderTransform).Clone();
            transform.X += delta.X;
            _wrapPanel.RenderTransform = transform;
            _lastMousePosition = _mousePosition;
        }
    }

一切正常

但我想要做的就是让用户点击拖动时,WrapPanel 中的项目会响应(即用户只是在浏览),但是当用户点击时(如在完整点击中那么他们确实响应了点击。

就像iphone的工作原理一样,当你直接在应用上按下并拖动它时,它不会打开应用程序,而是滚动屏幕,但当你点击应用程序时,它会启动......

我希望这是有道理的。

干杯, 标记

2 个答案:

答案 0 :(得分:3)

我相信你需要抓住鼠标。问题是你将与将试图捕获鼠标的控件(如Button)竞争。

在MouseDown事件中(实际上可能是PreviewMouseDown),您可以使用e.MouseDevice.Capture(_wrapPanel,CaptureMode.Element)。这应该将所有鼠标输入定向到_wrapPanel而不是任何子树元素。

在MouseUp事件中,您需要通过调用e.Mousedevice.Capture(null)来释放捕获。如果没有进行滚动,你会想要向通常会收到我不太确定的点击的控件发送“点击”。也许您可以使用Automation Peer类来执行此操作?

诀窍是,如果您从中隐藏鼠标事件,某些控件将无法正常工作。例如,考虑一个滑块。如何在这样工作的面板中使用滑块?

答案 1 :(得分:0)

另一个,在我看来更好的解决方案是:

  1. 添加一个PreviewMouseDown处理程序,在其中设置Handled = true并记录包括位置的参数并设置“maybeClick”标志(除非设置了“递归”标志),并设置一个计时器

  2. 添加MouseMove处理程序,如果鼠标移动的距离超过PreviewMouseDown记录的位置,则清除“maybeClick”标记。

  3. 添加一个检查“maybeClick”标志的PreviewMouseUp处理程序 - 如果为true,则设置“递归”标记,InputManager.ProcessInput重新提升原始PreviewMouseDown然后清除“递归”标志。

  4. 在计时器中,执行与PreviewMouseUp相同的操作,因此点击只会延迟片刻。

  5. 净效应是延迟PreviewMouseDown事件,直到您有时间检查鼠标是否移动为止。

    有关此解决方案的一些注意事项:

    • Handled=true上设置PreviewMouseDownEvent也会停止MouseDownEvent
    • PreviewMouseDown处理程序中忽略递归调用,因为设置了递归标记