我有一个通过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的工作原理一样,当你直接在应用上按下并拖动它时,它不会打开应用程序,而是滚动屏幕,但当你点击应用程序时,它会启动......
我希望这是有道理的。
干杯, 标记
答案 0 :(得分:3)
我相信你需要抓住鼠标。问题是你将与将试图捕获鼠标的控件(如Button)竞争。
在MouseDown事件中(实际上可能是PreviewMouseDown),您可以使用e.MouseDevice.Capture(_wrapPanel,CaptureMode.Element)。这应该将所有鼠标输入定向到_wrapPanel而不是任何子树元素。
在MouseUp事件中,您需要通过调用e.Mousedevice.Capture(null)来释放捕获。如果没有进行滚动,你会想要向通常会收到我不太确定的点击的控件发送“点击”。也许您可以使用Automation Peer类来执行此操作?
诀窍是,如果您从中隐藏鼠标事件,某些控件将无法正常工作。例如,考虑一个滑块。如何在这样工作的面板中使用滑块?
答案 1 :(得分:0)
另一个,在我看来更好的解决方案是:
添加一个PreviewMouseDown
处理程序,在其中设置Handled = true并记录包括位置的参数并设置“maybeClick”标志(除非设置了“递归”标志),并设置一个计时器
添加MouseMove
处理程序,如果鼠标移动的距离超过PreviewMouseDown
记录的位置,则清除“maybeClick”标记。
添加一个检查“maybeClick”标志的PreviewMouseUp
处理程序 - 如果为true,则设置“递归”标记,InputManager.ProcessInput
重新提升原始PreviewMouseDown
然后清除“递归”标志。
在计时器中,执行与PreviewMouseUp
相同的操作,因此点击只会延迟片刻。
净效应是延迟PreviewMouseDown
事件,直到您有时间检查鼠标是否移动为止。
有关此解决方案的一些注意事项:
Handled=true
上设置PreviewMouseDownEvent
也会停止MouseDownEvent
。PreviewMouseDown
处理程序中忽略递归调用,因为设置了递归标记