【问题标题】:How to cancel the dragging operation of a pointer如何取消指针的拖动操作
【发布时间】:2014-05-10 03:17:54
【问题描述】:

我正在寻找的是安装在 Windows 8.1 上的邮件应用程序。您开始拖动,随时可以按 Escape 键取消拖动。

我尝试了两件事,但都失败了:

  • 我保留了对 DragItemsStartingEventArgs 的引用,并在按下 Escape 键时设置了“dragItemsStartingEventArgs.Cancel = true”。
  • 我将 ListView CanDragItems 属性设置为 false。

我目前的假设是邮件应用程序是围绕 HTML5/JS 构建的,它具有 XAML 应用程序所没有的功能......我希望我错了。

谢谢 ArchieCoder

【问题讨论】:

  • 我想补充一点 - 如果用户可能不小心开始拖动或改变主意 - 并非所有人都知道转义键技巧,因此为了改进用户体验,您可以再添加两件事改进它 - 1. 尽可能为拖放操作启用撤消和 2. 提供一些不处理拖放数据的安全放置目标,但可能会给用户关于拖放操作的反馈,表明当用户拖放时它将被取消该目标和目标可能只是整个页面 - 除了对删除的数据进行操作的目标之外的任何地方。

标签: windows-runtime winrt-xaml windows-8.1


【解决方案1】:

啊,当然。你可以这样做。方法如下。

public sealed partial class MainPage : Page
{
    Pointer _Pointer = default(Pointer);
    public MainPage()
    {
        this.InitializeComponent();

        this.Dispatcher.AcceleratorKeyActivated += (s, e) =>
        {
            if (e.EventType == (CoreAcceleratorKeyEventType.SystemKeyDown & CoreAcceleratorKeyEventType.KeyDown)
                && e.VirtualKey == VirtualKey.Escape)
            { MyListView.ReleasePointerCapture(_Pointer); }
        };

        this.PointerMoved += (s, e) =>
        { _Pointer = e.Pointer; };
    }
}

另外,ListView 被命名为 MyListView。

祝你好运!

【讨论】:

  • 2014 年 5 月 6 日你是我的英雄 :)
  • 我会尽我所能。
  • +1 来自我的一个不错的 hack。现在让我们为平台添加拖放取消支持... :)
【解决方案2】:

我没有过多地使用拖放 API,所以我能看到的只有你尝试过的那些。不过,我最近确实发现(感谢 Tim Heuer 在某处提到)advanced input concepts 上的这个示例可能会有所帮助。我认为它描述了一个新到 8.1 的 API,它允许您处理 ScrollViewer 内部的操作事件(当您结合 SystemTranslateX/Y ManipulationModes)和 cancel scrolling 它们你不想再滚动了(例如,当您开始拖动时)。这可以让您使用您需要的任何功能实现自己的自定义拖放版本。

【讨论】:

    【解决方案3】:

    我认为值得讨论为什么保留对取消事件参数的引用不是解决方案,因为取消事件是如何编程的。稍后这对每个人来说都是值得的。所以,让我们假设我们要向太空发射火箭。 Fire() 方法本身可能如下所示。

    void Fire()
    {
        Rocket.Fire();
    }
    

    但是因为我们会让人们在它完成后对其做出反应,我们可能会创建一个AfterFire 事件来让人们知道它已经完成。它可能看起来像这样。

    event EventHandler AfterFire;
    void Fire()
    {
        Rocket.Fire();
        AfterFire(this, EventArgs.Empty);
    }
    

    实际上,您需要一些错误处理才能做到这一点。

    但是因为我们希望人们在实际开火行动之前询问火箭发射是否安全,所以我们添加了一个 BeforeFire 事件让人们知道它迫在眉睫。但是如果火箭不安全,我们希望包括取消的能力。像这样。

    class BeforeFireEventArgs: EventArgs { public bool Cancel { get; set; }}
    event EventHandler<BeforeFireEventArgs> BeforeFire;
    event EventHandler AfterFire;
    void Fire()
    {
        var args = new BeforeFireEventArgs();
        BeforeFire(this, args);
        if (args.Cancel)
            return;
        Rocket.Fire();
        AfterFire(this, EventArgs.Empty);
    }
    

    这里需要注意的是BeforeFireEventArgs是在这个方法中创建的,通过这个方法传递给事件,在事件返回到这个方法后进行询问。如果您要处理BeforeFire 事件,您可以将Cancel 设置为true,它不会触发。

    存在处理这种情况的 WinRT GetDeferral() 模式

    但是,如果您要处理 BeforeFire 事件,而不是将 Cancel 设置为 true,而是保留对 BeforeFireEventArgs 的引用以供以后使用,则处理程序将释放该事件,而 Cancel 将阻止或让火箭发射。

    然后,一分钟后,如果您使用 BeforeFireEventArgs 的相同引用并将 Cancel 设置为 true!时机已经太晚了。太晚了。该事件已被提出。已经处理好了。而Cancel 已经被审问了。

    有意义吗?

    【讨论】:

    • 完全理解你的解释!谢谢杰瑞。
    • 你是说 GetDeferral() 吗?
    • :) 老兄!您可以简单地更新答案。是的,延期,而不是推荐!呵呵!虽然我认为 Match.com 使用了这种方法。
    猜你喜欢
    • 1970-01-01
    • 2011-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多