WPF拖放vs操作
本文关键字:操作 vs 拖放 WPF | 更新日期: 2023-09-27 18:10:34
我想在具有IsManipulationEnabled = true
的父控件中启用子控件的拖放功能。
当操作被启用时,触摸事件不会被提升为鼠标事件。为了启用提升,应该在操作逻辑进入之前处理触摸事件(见示例)。我试过了,很管用……直到我第一次打电话给DoDragDrop
。然后我不再接收鼠标事件。为什么?
<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
...
如果我在MouseDown
中不调用DoDragDrop
-事件将得到应有的提升
看起来这是。net中的一个bug。我安装了v4.5.2。现在我已经安装了v4.6,这个问题不再重现了。
我甚至不需要将项目重新定位到v4.6或重新编译它:只是安装新的运行时修复了一切。
此解决方案适用于任何框架版本:
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
事件以重新启用操作。