使用Linq过滤System.Windows.Forms.Keys的可能值

时间:2009-10-18 19:24:24

标签: c# wpf linq keyboard-shortcuts

我正在使用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”。我不知道为什么。

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

3 个答案:

答案 0 :(得分:9)

您有两个错别字 - 您使用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);

答案 1 :(得分: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;

答案 2 :(得分:0)

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

通过属性过滤掉实际的枚举值将更加简单明了。 请注意,在这种情况下,您的AttributeTarget应为Field。