即使我们没有在WPF中按“Alt”键,也会选择访问键

时间:2011-12-09 10:16:39

标签: wpf wpf-controls access-keys

我有WPF应用程序,它有工具栏。在工具栏中,我将一些用户控件作为工具。

我已经为每个控件设置了访问键,它工作正常。

问题是:如果我单击一个用户控件(由Button和Label组成,我已经为Button设置了访问键),给定的任务就完成了,但是当我按任意一个访问键而不按'Alt'键然后它正在被选中。

有什么想法吗?

3 个答案:

答案 0 :(得分:3)

显然,这是微软的故意改变。请参阅Atanas Koralski的回答:

http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/14f6f49f-0027-471b-b68c-e7f6ba012012

  

菜单和工具栏助记符无需按Alt键即可工作。我们决定   我们将在所有情况下都有统一的行为,因此访问关键工作   不按Alt键。

     

据我所知,这与表格不符,我们会   请考虑此问题并更改下一版本中的行为。

     

现在作为一种解决方法,您可以为所有人注册一个类处理程序   AccessKeyPressed事件并在Alt键不处理时处理事件   按压。

EventManager.RegisterClassHandler(typeof(UIElement),
AccessKeyManager.AccessKeyPressedEvent,
new AccessKeyPressedEventHandler(OnAccessKeyPressed));
     

...

private static void OnAccessKeyPressed(object sender, AccessKeyPressedEventArgs e)
{
    if (!e.Handled && e.Scope == null && (e.Target == null || e.Target == label))
    {
        // If Alt key is not pressed - handle the event
        if ((Keyboard.Modifiers & ModifierKeys.Alt) != ModifierKeys.Alt)
        {
            e.Target = null;
            e.Handled = true;
        }
    }
}

另见mfc2wpf的回复:

  

我已使用上述内容并且有效。但是,这阻止了默认   Enter和ESC的操作。所以我在顶部插入了以下内容   方法。

if (Keyboard.IsKeyDown(Key.Enter) || Keyboard.IsKeyDown(Key.Escape)) return;

访问键包括 Enter Esc ,它们是ButtonIsDefault = true的{​​{1}}的默认键。如果您不想要 Alt + Enter Alt + Esc 这些按钮,则需要将特殊条件添加到处理程序。

答案 1 :(得分:2)

从.Net 4.5开始,您可以使用CoreCompatibilityPreferences.IsAltKeyRequiredInAccessKeyDefaultScope属性配置此行为。要更改访问键行为,以便只在按下Alt时触发它们,请将其设置为true。

function split(a, n) {
    var len = a.length,out = [], i = 0;
    while (i < len) {
        var size = Math.ceil((len - i) / n--);
        out.push(a.slice(i, i += size));
    }
    return out;
}
var data = ["Michael", "Marc", "John", "David", "Nick", "Mom", "Al", "Marlana", "Max", 
            "Scooter", "Pat", "George", "Lynne", "Tatyana", "Kim", "Kerry", "Enza", "Matt",
            "Liz", "Linda", "Ryan",
            "Ed", "Frank", "Christine", "Bill", "Jack", "Jill", "Joe", "Harry", "Red",
            "Fred", "Iggy", "Brian", "Bob", "Paul", "Gil", "Damian", "Kip", "Phil", "Curtis", "Aly",
           "Richard", "Robin", "Grant", "Ian", "Raptor", "T-Rex", "Stegosaurux", "Triceratops", "Compy"]

sixteengroup = split(data, data.length/16);
document.write(JSON.stringify(sixteengroup));

正如文档所述,这必须在应用程序的早期。设置它会在读完后抛出异常。

答案 2 :(得分:0)

如其他答案中所述,设置IsAltKeyRequiredInAccessKeyDefaultScope可以避免在不按 Alt 键的情况下调用访问键的操作。但是,这也可以禁用 Enter 键(用于调用默认操作)和 Esc 键(用于调用Cancel操作)。

使用建议的解决方法,并测试Key.EnterKey.Escape,可以避免此问题。但是,您可能会发现,如果不按 Alt 键,则无法通过其访问键选择菜单项,如果范围中的按钮使用相同的访问密钥,则可能会出现问题。

然后,另一种方法是通过检查可能可调用的AccessText控件是否在MenuItem范围内来处理访问键事件,这些内容如下:

EventManager.RegisterClassHandler(
  typeof(UIElement),
  AccessKeyManager.AccessKeyPressedEvent,
  new AccessKeyPressedEventHandler(OnAccessKeyPressed));

...

static void OnAccessKeyPressed(object accessKeyTarget, AccessKeyPressedEventArgs e)
{
  if (!e.Handled && e.Scope == null &&
    (Keyboard.Modifiers & ModifierKeys.Alt) != ModifierKeys.Alt &&
    !ShouldElementHandleAccessKeysWhenAltIsNotPressed(accessKeyTarget as UIElement))
  {
    e.Target = null;
    e.Handled = true;
  }
}

static bool ShouldElementHandleAccessKeysWhenAltIsNotPressed(UIElement element)
{
  if (element == null) return false;
  var accessText = element as AccessText;
  if (accessText != null && !IsDecendantOfMenuItem(accessText)) return false;
  return true;
}

static bool IsDecendantOfMenuItem(DependencyObject element)
{
  for (; element != null; element = VisualTreeHelper.GetParent(element))
    if (element is MenuItem) return true;
  return false;
}