【问题标题】:Using Linq to filter possible values of System.Windows.Forms.Keys使用 Linq 过滤 System.Windows.Forms.Keys 的可能值
【发布时间】:2009-10-18 19:24:24
【问题描述】:

我正在使用 WPF 创建一个选项对话框,其中列出了可能的键,以便用户可以分配程序的热键。我正在尝试将 System.Windows.Forms.Keys 枚举的所有可能值过滤到仅 A-Z 和 F1-F12,然后将该列表绑定到 ComboBox。

到目前为止,这是我的代码:

Regex filter = new Regex("(^[A-Z]$)|(^F[0-9]{1,2}$)");
IEnumerable<Key> keyList = from x in (IEnumerable<Key>)Enum.GetValues(typeof(Keys)) 
                           where filter.Match(x.ToString()).Success
                           select x;
keys.DataContext = keyList;

执行此操作后,keyList 包含字母“A”两次,并且缺少字母“P”到“U”。我不知道为什么。

如果有更好的方法,我也对替代方法感兴趣。

【问题讨论】:

    标签: c# wpf linq keyboard-shortcuts


    【解决方案1】:

    您有两个拼写错误 - 您使用了两次 System.Windows.Input.Key 而不是 System.Windows.Forms.Keys。多么不幸的错别字!我建议除非你真的需要在同一个文件中同时使用 WinForms 和 WPF 的指令,否则不要同时使用它们。

    这是一个简短但完整的有效示例(基于您的代码,但拼写错误已修复):

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text.RegularExpressions;
    using System.Windows.Forms;
    
    class Test
    {
        static void Main()        
        {
            Regex filter = new Regex("(^[A-Z]$)|(^F[0-9]{1,2}$)");
            IEnumerable<Keys> keyList = 
                from x in (IEnumerable<Keys>) Enum.GetValues(typeof(Keys)) 
                where filter.Match(x.ToString()).Success
                select x;
    
    
            foreach (var key in keyList)
            {
                Console.WriteLine(key);
            }
        }
    }
    

    请注意,您可以使用显式类型的范围变量更轻松地编写查询表达式:

    IEnumerable<Keys> keyList = from Keys x in Enum.GetValues(typeof(Keys)) 
                                where filter.Match(x.ToString()).Success
                                select x;
    

    或者使用点符号开始:

    var keyList = Enum.GetValues(typeof(Keys))
                      .Cast<Keys>()
                      .Where(x => filter.Match(x.ToString()).Success);
    

    或者,您可以使用Unconstrained Melody 并获得一个强类型列表开始:

    var keyList = Enums.GetValues<Keys>()
                       .Where(x => filter.Match(x.ToString()).Success);
    

    【讨论】:

    • 谢谢,乔恩。这里有很多很棒的信息。我想我可能正在做一些相当愚蠢的事情来得到那些奇怪的结果。
    【解决方案2】:

    Jon's post 指出了拼写错误和不同命名空间的问题。它也适用于我。不过,我想指出一些关于正则表达式方面的事情。

    您的正则表达式可以增强。目前它返回 A-Z 和 F1-F24。要将其限制为 F1-12,请改用此模式:"^([A-Z]|F([1-9]|1[0-2]))$" - 请注意,我还对其进行了重构以避免 ^$ 锚重复。

    此外,您可以使用IsMatch 代替匹配和成功:

    Regex filter = new Regex("^([A-Z]|F([1-9]|1[0-2]))$");
    IEnumerable<Keys> keyList =
        from x in (IEnumerable<Keys>)Enum.GetValues(typeof(Keys)) 
        where filter.IsMatch(x.ToString())
        select x;
    

    【讨论】:

      【解决方案3】:

      您是否考虑过使用自定义属性标记枚举值(类似于 'HotKeyAttribute')

      比通过属性过滤掉实际的枚举值更简单。 请注意,在这种情况下,您的 AttributeTarget 应该是 Field。

      【讨论】:

      • 这些是框架提供的枚举值 - OP 不会对它们进行注释。
      • 哦,没意识到。尴尬:-\
      猜你喜欢
      • 1970-01-01
      • 2017-06-04
      • 2014-05-07
      • 1970-01-01
      • 2015-07-12
      • 2011-01-30
      • 1970-01-01
      • 1970-01-01
      • 2011-07-02
      相关资源
      最近更新 更多