I'm creating an options dialog using WPF that lists possible keys so that the user can assign the program's hotkey. I'm attempting to filter all of the possible values of the System.Windows.Forms.Keys enumeration down to just A-Z and F1-F12, and then bind that list to a ComboBox.
我正在使用WPF创建一个选项对话框,该对话框列出可能的键,以便用户可以分配程序的热键。我试图过滤系统的所有可能值。键枚举到a - z和F1-F12,然后将该列表绑定到ComboBox。
Here's my code so far:
这是我到目前为止的代码:
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;
After executing this, keyList contains the letter "A" twice and is missing letters "P" through "U." I'm at a loss as to why.
在执行此操作后,keyList包含字母“A”两次,并通过“u”丢失字母“P”。我不知道为什么。
I'm also interested in alternate approaches, if there's a better way.
如果有更好的方法,我也对其他方法感兴趣。
3 个解决方案
#1
9
You had two typos - you were using System.Windows.Input.Key
instead of System.Windows.Forms.Keys
twice. What an unfortunate typo! I would suggest that unless you really need using directives for both WinForms and WPF in the same file, you avoid having them both there.
你有两个拼写错误——你用的是System.Windows.Input。关键不是System.Windows.Forms。键两次。一个不幸的错误!我建议,除非您确实需要在同一个文件中使用WinForms和WPF的指令,否则应该避免它们同时存在。
Here's a short but complete example that works (based on your code, but with the typos fixed):
这里有一个简短但完整的示例(基于您的代码,但是错误是固定的):
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);
}
}
}
Note that you can write the query expression more easily by using an explicitly typed range variable:
注意,通过使用显式类型化范围变量,可以更容易地编写查询表达式:
IEnumerable<Keys> keyList = from Keys x in Enum.GetValues(typeof(Keys))
where filter.Match(x.ToString()).Success
select x;
Or use dot notation to start with:
或以点表示法开始:
var keyList = Enum.GetValues(typeof(Keys))
.Cast<Keys>()
.Where(x => filter.Match(x.ToString()).Success);
Alternatively, you could use Unconstrained Melody and get a strongly typed list to start with:
或者,您可以使用无约束的旋律,并得到一个强类型的列表,以开始:
var keyList = Enums.GetValues<Keys>()
.Where(x => filter.Match(x.ToString()).Success);
#2
2
Jon's post pointed out the typos and different namespaces issue. It works for me as well. However, I wanted to point out a few things on the regex side of things.
Jon的文章指出了拼写错误和不同命名空间的问题。对我来说也一样。然而,我想指出regex方面的一些事情。
Your regex can be enhanced. Currently it returns A-Z and F1-F24. To restrict it to F1-12 use this pattern instead: "^([A-Z]|F([1-9]|1[0-2]))$"
- notice that I also refactored it to avoid the ^$
anchor repetition.
你的正则表达式可以被增强。目前它返回A-Z和F1-F24。限制它F1-12使用这种模式而不是:" ^[a - z]|(F((1 - 9)| 1[0]))$”——注意,我也重构避免^ $锚重复。
Additionally, you can use IsMatch
instead of Match and Success:
此外,你可以使用IsMatch而不是Match和Success:
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
0
Have you considered marking the enumeration values with a custom attribute (something like 'HotKeyAttribute')
您是否考虑过使用自定义属性(比如“HotKeyAttribute”)标记枚举值
Than- filtering out the actual enum values by the attribute will be mucj more straightforward. Note that in this case your AttributeTarget should be Field.
通过属性过滤出实际的enum值将更加简单。注意,在这种情况下,AttributeTarget应该是字段。
#1
9
You had two typos - you were using System.Windows.Input.Key
instead of System.Windows.Forms.Keys
twice. What an unfortunate typo! I would suggest that unless you really need using directives for both WinForms and WPF in the same file, you avoid having them both there.
你有两个拼写错误——你用的是System.Windows.Input。关键不是System.Windows.Forms。键两次。一个不幸的错误!我建议,除非您确实需要在同一个文件中使用WinForms和WPF的指令,否则应该避免它们同时存在。
Here's a short but complete example that works (based on your code, but with the typos fixed):
这里有一个简短但完整的示例(基于您的代码,但是错误是固定的):
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);
}
}
}
Note that you can write the query expression more easily by using an explicitly typed range variable:
注意,通过使用显式类型化范围变量,可以更容易地编写查询表达式:
IEnumerable<Keys> keyList = from Keys x in Enum.GetValues(typeof(Keys))
where filter.Match(x.ToString()).Success
select x;
Or use dot notation to start with:
或以点表示法开始:
var keyList = Enum.GetValues(typeof(Keys))
.Cast<Keys>()
.Where(x => filter.Match(x.ToString()).Success);
Alternatively, you could use Unconstrained Melody and get a strongly typed list to start with:
或者,您可以使用无约束的旋律,并得到一个强类型的列表,以开始:
var keyList = Enums.GetValues<Keys>()
.Where(x => filter.Match(x.ToString()).Success);
#2
2
Jon's post pointed out the typos and different namespaces issue. It works for me as well. However, I wanted to point out a few things on the regex side of things.
Jon的文章指出了拼写错误和不同命名空间的问题。对我来说也一样。然而,我想指出regex方面的一些事情。
Your regex can be enhanced. Currently it returns A-Z and F1-F24. To restrict it to F1-12 use this pattern instead: "^([A-Z]|F([1-9]|1[0-2]))$"
- notice that I also refactored it to avoid the ^$
anchor repetition.
你的正则表达式可以被增强。目前它返回A-Z和F1-F24。限制它F1-12使用这种模式而不是:" ^[a - z]|(F((1 - 9)| 1[0]))$”——注意,我也重构避免^ $锚重复。
Additionally, you can use IsMatch
instead of Match and Success:
此外,你可以使用IsMatch而不是Match和Success:
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
0
Have you considered marking the enumeration values with a custom attribute (something like 'HotKeyAttribute')
您是否考虑过使用自定义属性(比如“HotKeyAttribute”)标记枚举值
Than- filtering out the actual enum values by the attribute will be mucj more straightforward. Note that in this case your AttributeTarget should be Field.
通过属性过滤出实际的enum值将更加简单。注意,在这种情况下,AttributeTarget应该是字段。