【问题标题】:How to catch mouse movement when left mouseButton is pressed on a button control and released on different button control?当在按钮控件上按下鼠标左键并在不同的按钮控件上释放时,如何捕捉鼠标移动?
【发布时间】:2013-06-21 03:32:12
【问题描述】:

我在 WPF 中创建了一个自定义用户控件,如附图所示,我想鼠标左键单击按钮“8”并按住鼠标按钮移动另一个按钮,例如:按钮“1”并释放鼠标左键。现在我想在单击它时获得两个按钮“8”,在释放按钮时获得“1”。我已经注册了 PreviewMouseLeftButtonDown 以获取鼠标按下事件和 PreviewMouseLeftButtonUp 以获取鼠标向上事件。但是当我点击“8”并在两个事件中移动“1”释放按钮时,我得到相同的“8”按钮。 谁能告诉我如何实现这一目标。

private ToggleButton _startButton;
private ToggleButton _endButton;

private void tb_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
  _startButton = sender as ToggleButton;
}

private void tb_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
  _endButton = sender as ToggleButton;
  if (_endButton != null && _startButton != null)
  {
    string start = _startButton.Content.ToString();
    string end = _endButton.Content.ToString();
    if (!start.Equals(end))
      ToggleButton(_endButton);
  }
}

【问题讨论】:

    标签: c# wpf


    【解决方案1】:

    这种行为是由于鼠标被捕获而引起的。尝试使用命中测试来获取位于鼠标释放点的元素:http://msdn.microsoft.com/en-us/library/ms608752.aspx

    更新

    例如,您有以下布局:

    <Window x:Class="WpfApplication24.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <StackPanel>
            <Button Content="b1" PreviewMouseLeftButtonUp="Button_PreviewMouseLeftButtonUp_1"/>
            <Button Content="b2"/>
        </StackPanel>
    </Window>
    

    在您的 PreviewMouseLeftButtonUp 处理程序上,您应该执行以下代码:

    private void Button_PreviewMouseLeftButtonUp_1(object sender, MouseButtonEventArgs e) {
        var result = VisualTreeHelper.HitTest(this, e.GetPosition(this));            
    }
    

    请注意,您应该将 HitTest 用于两个按钮的共同父元素(例如 - 它是 MainWindow)

    在 result.VisualHit 属性中,您可以看到光标下的元素。

    之后,您可以使用 VisualTreeHelper 来检查它是否是您的 Button 的子级,或者尝试以下方法:

    1)创建一些标志附加属性:

    public static bool GetIsHitTestTarget(DependencyObject obj) {
        return (bool)obj.GetValue(IsHitTestTargetProperty);
    }
    public static void SetIsHitTestTarget(DependencyObject obj, bool value) {
        obj.SetValue(IsHitTestTargetProperty, value);
    }
    public static readonly DependencyProperty IsHitTestTargetProperty = DependencyProperty.RegisterAttached("IsHitTestTarget", typeof(bool), typeof(MainWindow), new PropertyMetadata(false));
    

    2) 为您应该找到的元素设置它的值:

    <Button Content="b1" local:MainWindow.IsHitTestTarget="true" PreviewMouseLeftButtonUp="Button_PreviewMouseLeftButtonUp_1"/>
    <Button Content="b2" local:MainWindow.IsHitTestTarget="true"/>
    

    3) 修改 PreviewLeftButtonUp 回调:

    private void Button_PreviewMouseLeftButtonUp_1(object sender, MouseButtonEventArgs e) {
        DependencyObject result = null;
        VisualTreeHelper.HitTest(this,        
            (o)=> {if(GetIsHitTestTarget(o)) {
                result = o;
                return HitTestFilterBehavior.Stop;
            }
            return HitTestFilterBehavior.Continue;
            },
            (res) => HitTestResultBehavior.Stop,
            new PointHitTestParameters(e.GetPosition(this)));
    }
    

    【讨论】:

    • 我已将此代码添加到我的方法中:Point pt = e.GetPosition((UIElement)sender); // 对可视对象树的给定部分执行命中测试。 HitTestResult 结果 = VisualTreeHelper.HitTest(this.Parent as Visual, pt);如果(结果 == null)返回;但我总是得到结果值为空。我已将父控件作为视觉参考参数传递,我也尝试传递与 Visual refence bt 相同的控件,在这两种情况下我都得到空命中结果,有没有其他方法来获取元素。
    • 我已经修改了我之前的答案,向您展示它是如何工作的
    • 感谢 ASerov 的支持。代码按预期工作。 -:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-19
    相关资源
    最近更新 更多