WPF Drag& Drop vs操纵

时间:2015-09-01 06:19:50

标签: c# wpf drag-and-drop touch

我想在拥有IsManipulationEnabled = true的父级中启用“拖放”子控件。

启用操作后,触摸事件不会升级为鼠标事件。为了实现促销,应该在操作逻辑步骤之前处理触摸事件(参见example)。我已经尝试过了,但它确实有效......直到我第一次给DoDragDrop打电话。然后我不再收到鼠标事件。为什么呢?

这是重现问题的最小代码。为了便于阅读,删除了所有拖放操作。

XAML:

<Window x:Class="Test.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="300" Width="300" IsManipulationEnabled="True">
    <Grid>
        <Border Background="Red" 
                x:Name="Border"
                TouchDown="Border_OnTouchDown"
                MouseDown="Border_OnMouseDown"
                TouchUp="Border_OnTouchUp"
                Width="100" Height="50" />
    </Grid>
</Window>

C#:

public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();
    }

    private void Border_OnTouchDown(object sender, TouchEventArgs e)
    {
        Debug.WriteLine("Border_OnTouchDown");
        e.Handled = true;
        e.TouchDevice.Capture((FrameworkElement)sender);
    }

    private void Border_OnMouseDown(object sender, MouseButtonEventArgs e)
    {
        Debug.WriteLine("Border_OnMouseDown!");
        DragDrop.DoDragDrop((DependencyObject)sender, "", DragDropEffects.All);
    }

    protected override void OnManipulationStarted(ManipulationStartedEventArgs e)
    {
        Debug.WriteLine("OnManipulationStarted");
        base.OnManipulationStarted(e);
    }

    private void Border_OnTouchUp(object sender, TouchEventArgs e)
    {
        ((FrameworkElement)sender).ReleaseTouchCapture(e.TouchDevice);
        e.Handled = true;
    }
}

输出:

Border_OnTouchDown
Border_OnMouseDown! <- works first time
Border_OnTouchDown 
Border_OnTouchDown  <- no longer works, no matter how many times I tap
Border_OnTouchDown
Border_OnTouchDown
Border_OnTouchDown
...

如果我没有在DoDragDrop中致电MouseDown - 活动会得到应有的提升。

2 个答案:

答案 0 :(得分:2)

看起来这是.NET中的一个错误。我安装了v4.5.2。现在我已经安装了v4.6,问题不再可重现。

我甚至不必将项目重新定位到v4.6或重新编译它:只是安装新的运行时修复了所有内容。

答案 1 :(得分:0)

此解决方案适用于任何框架版本:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void Border_OnTouchDown(object sender, TouchEventArgs e)
    {
        Debug.WriteLine("Border_OnTouchDown");

        IsManipulationEnabled = false;
        e.TouchDevice.Capture(Border);
    }

    private void Border_OnMouseDown(object sender, MouseButtonEventArgs e)
    {
        Debug.WriteLine("Border_OnMouseDown!");
        DragDrop.DoDragDrop((DependencyObject)sender, "", DragDropEffects.All);
    }

    protected override void OnManipulationStarted(ManipulationStartedEventArgs e)
    {
        Debug.WriteLine("OnManipulationStarted");
        base.OnManipulationStarted(e);
    }

    private void Border_OnTouchUp(object sender, TouchEventArgs e)
    {
        Border.ReleaseTouchCapture(e.TouchDevice);
        IsManipulationEnabled = true;
    }
}

如果用户触摸Border,我们基本上禁用操作。由于拖放操作可能(并且可能会)在Border之外结束,我们还需要捕获触摸输入以确保接收TouchUp事件以重新启用操作。