简体   繁体   English

如何在 UWP 中的“Enter”上关闭 ContentDialog

[英]How to close ContentDialog on "Enter" in UWP

I've been trying to get a simple ContentDialog with a TextBox to close when the user hits Enter while still in the TextBox .我一直在尝试让一个带有TextBox的简单ContentDialog在用户仍然在TextBox点击Enter时关闭。 Sadly it doesn't even work without a TextBox , even though the ContentDialog responds to Esc .遗憾的是,即使 ContentDialog 响应Esc ,它在没有TextBox情况下也无法工作。

I was hoping there was a way to set a Result from inside the KeyDown Handler of the TextBox , but it seems ContentDialog lacks this?!我希望有一种方法可以从TextBoxKeyDown处理程序内部设置 Result ,但似乎ContentDialog缺少这个?!

You can close the ContentDialog using Hide() method in TextBox KeyDown handler, simple example:您可以在TextBox KeyDown处理程序中使用Hide()方法关闭 ContentDialog,简单示例:

ContentDialog c = new ContentDialog();

var tb = new TextBox();

tb.KeyDown += (sender, args) =>
{
     if (args.Key == VirtualKey.Enter)
     {
          c.Hide();
     }
};

c.Content = tb;
c.ShowAsync();

EDIT: But it seems to be more complicated when you want to close the dialog without TextBox .编辑:但是当您想在没有TextBox情况下关闭对话框时似乎更复杂。 You have to subscribe on global Window.Current.CoreWindow.KeyDown event:您必须订阅全局Window.Current.CoreWindow.KeyDown事件:

ContentDialog c = new ContentDialog();

Window.Current.CoreWindow.KeyDown += (sender, args) =>
{
      if (args.VirtualKey == VirtualKey.Enter)
      {
            c.Hide();
      }
};
c.ShowAsync();

Here is my final solution that would get me a ContentDialogResult.Primary on Enter这是我的最终解决方案,它可以让我在Enter 时获得ContentDialogResult.Primary

I added this to my ContentDialog:我将此添加到我的 ContentDialog 中:

    public new IAsyncOperation<ContentDialogResult> ShowAsync()
    {
        var tcs = new TaskCompletionSource<ContentDialogResult>();

        CaptionTB.KeyDown += (sender, args) =>
        {
            if (args.Key != VirtualKey.Enter) return;
            tcs.TrySetResult(ContentDialogResult.Primary);
            Hide();
            args.Handled=true;
        };

        var asyncOperation = base.ShowAsync();
        asyncOperation.AsTask().ContinueWith(task => tcs.TrySetResult(task.Result));
        return tcs.Task.AsAsyncOperation();
    }

unfortunately ShowAsync isn't virtual so I had to new the function.不幸的是ShowAsync不是虚拟的,所以我不得不new这个函数。 It works well for me though!不过对我来说效果很好!

The short answer is that it isn't (cleanly) possible without workarounds and hacks that will preserve the functionality of identifying which button was pressed.简短的回答是,如果没有解决方法和黑客攻击,就不可能(完全)可能保留识别按下哪个按钮的功能。 The long answer is that it's fortunately very clean and easy to subclass ContentDialog to do exactly what we want:很长的答案是,幸运的是,将ContentDialog子类ContentDialog我们想要的东西是非常干净和容易的:

using System;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;

namespace NeoSmart.Dialogs
{
    class HotkeyContentDialog : ContentDialog
    {
        public new event TypedEventHandler<ContentDialog, ContentDialogButtonClickEventArgs> PrimaryButtonClick;
        public new event TypedEventHandler<ContentDialog, ContentDialogButtonClickEventArgs> SecondaryButtonClick;

        public ContentDialogResult Result { get; set; }
        public new async Task<ContentDialogResult> ShowAsync()
        {
            var baseResult = await base.ShowAsync();
            if (baseResult == ContentDialogResult.None)
            {
                return Result;
            }
            return baseResult;
        }

        protected override void OnKeyUp(KeyRoutedEventArgs e)
        {
            if (e.Key == Windows.System.VirtualKey.Enter)
            {
                Result = ContentDialogResult.Primary;
                PrimaryButtonClick?.Invoke(this, default(ContentDialogButtonClickEventArgs));
                Hide();
            }
            else if (e.Key == Windows.System.VirtualKey.Escape)
            {
                Result = ContentDialogResult.Secondary;
                SecondaryButtonClick?.Invoke(this, default(ContentDialogButtonClickEventArgs));
                Hide();
            }
            else
            {
                base.OnKeyUp(e);
            }
        }
    }
}

Just use HotkeyContentDialog instead of ContentDialog and all will be well.只需使用HotkeyContentDialog而不是ContentDialog一切都会好起来的。

It has been a while since this question has been asked, but a ContentDialog has a DefaultButton property that handles Enter in the way you want.自从提出这个问题以来已经有一段时间了,但是 ContentDialog 有一个 DefaultButton 属性,可以按照您想要的方式处理 Enter。

ContentDialog.DefaultButton ContentDialog.DefaultButton

For a TextBox, I assume you have to set the AcceptsReturn property to false because this may interfere with the Enter that is intended to close the dialog.对于 TextBox,我假设您必须将 AcceptsReturn 属性设置为 false,因为这可能会干扰旨在关闭对话框的 Enter。

TextBox.AcceptsReturn TextBox.AcceptsReturn

Mahmouds solution is more than perfect! Mahmouds 解决方案非常完美! Should be accepted as answer IMO.应该被接受为 IMO 的答案。 Here is the further reworked HotkeyContentDialog class from me:这是我进一步重新设计的 HotkeyContentDialog 类:

public class HotkeyContentDialog : ContentDialog
{
    public new event TypedEventHandler<ContentDialog, ContentDialogButtonClickEventArgs> PrimaryButtonClick;
    public new event TypedEventHandler<ContentDialog, ContentDialogButtonClickEventArgs> SecondaryButtonClick;
    public ContentDialogResult Result { get; set; }

    public new async Task<ContentDialogResult> ShowAsync()
    {
        var baseResult = await base.ShowAsync();
        return baseResult == ContentDialogResult.None ? Result : baseResult;
    }

    protected override void OnKeyUp(KeyRoutedEventArgs e)
    {
        switch (e.Key)
        {
            case Windows.System.VirtualKey.Enter:
                Result = ContentDialogResult.Primary;
                PrimaryButtonClick?.Invoke(this, default);
                Hide();
                break;
            case Windows.System.VirtualKey.Escape:
                Result = ContentDialogResult.Secondary;
                SecondaryButtonClick?.Invoke(this, default);
                Hide();
                break;
            default:
                base.OnKeyUp(e);
                break;
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM