How to close ContentDialog on "Enter" in UWP

时间:2015-12-08 19:27:09

标签: c# uwp

I've been trying to get a simple a,b Harry Potter c Ron Wesley with a ContentDialog to close when the user hits Enter while still in the TextBox. Sadly it doesn't even work without a TextBox, even though the ContentDialog responds to Esc.

I was hoping there was a way to set a Result from inside the TextBox Handler of the KeyDown, but it seems TextBox lacks this?!

5 个答案:

答案 0 :(得分:5)

您可以使用Hide() TextBox处理程序中的KeyDown方法关闭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();

修改 但是,如果要关闭没有TextBox的对话框,它似乎会更复杂。您必须订阅全球Window.Current.CoreWindow.KeyDown活动:

ContentDialog c = new ContentDialog();

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

答案 1 :(得分:2)

这是我的最终解决方案,可以在{kbd>输入

上找到ContentDialogResult.Primary

我将此添加到我的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();
    }

遗憾的是ShowAsync不是虚拟的,所以我不得不new这个功能。虽然它适合我!

答案 2 :(得分:2)

简短的回答是,如果没有变通方法和黑客攻击,它就不会(干净地)可以保留识别按下按钮的功能。很长的答案是,幸运的是,非常干净,很容易将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);
            }
        }
    }
}

只需使用HotkeyContentDialog代替ContentDialog,一切都会好起来。

答案 3 :(得分:1)

Mahmouds解决方案远非完美!应作为IMO的答案。这是我进一步改进的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;
        }
    }
}

答案 4 :(得分:0)

问这个问题已经有一段时间了,但是ContentDialog具有DefaultButton属性,该属性可以按您想要的方式处理Enter。

ContentDialog.DefaultButton

对于TextBox,我假设您必须将AcceptsReturn属性设置为false,因为这可能会干扰旨在关闭对话框的Enter。

TextBox.AcceptsReturn