2

I'm writing an app that uses the "tabbed browsing" metaphor, with a TabControl the full size of the window, and other stuff inside the tabs. Sometimes those tabs will themselves contain other TabControls.

(Tabs inside tabs can be confusing, so I'll re-style the inner TabControl so it doesn't look like a TabControl. I'll probably style it to use ToggleButtons at the top instead of tabs.)

I want this UI to behave like you would expect the tabbed-browsing metaphor to work: Ctrl+Tab should always switch tabs on the outer TabControl (the one that looks like a TabControl), even if keyboard focus is inside the inner TabControl (which doesn't look like a TabControl, and therefore shouldn't be expected to respond to Ctrl+Tab). But, of course, the inner TabControl gets the key event first and handles it itself.

What's the best way to keep the inner TabControl from responding to the Ctrl+Tab and Ctrl+Shift+Tab key events, so those events can bubble up to the outer TabControl?

4

3 回答 3

3

WPF TabControl 似乎通过 OnKeyDown 方法管理键盘导航功能。我建议创建一个从 TabControl 继承的自定义控件,并覆盖 OnKeyDown 方法。

于 2009-05-07T13:37:21.300 回答
1

作为此处建议的创建自定义控件的替代方法,您可以创建一个“附加行为”来封装它:

namespace WpfApplication1
{
  using System.Windows;
  using System.Windows.Input;

  public static class IgnoreCtrlTabBehaviour
  {
    //Setter for use in XAML: this "enables" this behaviour
    public static void SetEnabled(DependencyObject depObj, bool value)
    {
      depObj.SetValue(EnabledProperty, value);
    }

    public static readonly DependencyProperty EnabledProperty =
        DependencyProperty.RegisterAttached("Enabled", typeof(bool), 
        typeof(IgnoreCtrlTabBehaviour), 
        new FrameworkPropertyMetadata(false, OnEnabledSet));

    static void OnEnabledSet(DependencyObject depObj, DependencyPropertyChangedEventArgs args)
    {
      var uiElement = depObj as UIElement;
      uiElement.PreviewKeyDown += 
        (object _, System.Windows.Input.KeyEventArgs e) => 
        {
          if (e.Key == Key.Tab && 
              (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
          {
            e.Handled = true;
          }
        };
      }
    }
  }

像这样在 XAML 中使用:

<Window x:Class="WpfApplication1.MainWindow"
    ...
    xmlns:local="clr-namespace:WpfApplication1"

...
<TabControl local:IgnoreCtrlTabBehaviour.Enabled="True">
  <TabItem Header="tab1">
...
于 2012-12-18T16:18:16.670 回答
1

您可以在内部 TabControl 上处理 PreviewKeyDown 事件并设置 e.Handled = true 以防止它处理关键事件。然后,您可以找到父 TabControl(可能通过 ((TabControl)sender).Parent 递归)并以编程方式更改其 SelectedIndex。

将其包装在自定义控件中将使其保持相当干净。

于 2009-05-07T13:46:04.490 回答