使用ControlTemplate内的控件进行焦点处理

时间:2013-07-10 12:56:20

标签: wpf focus controltemplate

当您编写自己的控件并在其控件模板中包含控件时,管理焦点的正确方法是什么?


假设我们在ControlTemplate中有一个带有两个TextBox的CustomControl。作为用户和开发人员,我期望以下行为:

  1. 调用customControl.Focus()时,模板中的第一个TextBox应该获得焦点。

  2. 使用Tab / Shift + Tab向前和向后移动焦点预计会起作用,这意味着:

  3. 2.1如果用户在customControl之前按下控件中具有焦点的Tab,则焦点应移动到customControl的第一个文本框。

    2.2如果用户按下Shift + Tab,焦点位于自定义控件的第一个文本框中,则焦点应移至customControl之前的任何控件。


    我已经尝试过了:

    一个。将CustomControl设置为Focusable = false启用条件2.但禁用条件1。

    湾在StackOverflow上,如何将焦点移动到控件模板内的控件的问题多次出现。始终提出以下解决方案:

    <Trigger Property="IsFocused" Value="True">
      <Setter TargetName="PART_TextBox1" Property="FocusManager.FocusedElement" Value="{Binding ElementName=PART_TextBox1}" />
    </Trigger>
    

    此解决方案启用条件1和2.1但会破坏条件2.2。

    感谢您的帮助:)

1 个答案:

答案 0 :(得分:3)

您可以使用第二个选项(IsFocused属性上的触发器)并通过简单地将CustomControl的IsTabStop属性设置为False来保持条件2.2。这个解决方案的一个重大缺陷是,通过将IsTabStop属性设置回True可以轻松撤消。

实现目标的另一种方法是放弃触发器并在控件的代码隐藏中处理焦点更改,如下所示:

protected override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e)
{
    base.OnGotKeyboardFocus(e);
    if (e.NewFocus == this)
    {
        if (object.ReferenceEquals(e.OldFocus, Template.FindName("PART_TextBox1", this)))
            MoveFocus(new TraversalRequest(FocusNavigationDirection.Previous));
        else
            MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
    }
}

我还建议在您的模板中的任何可聚焦控件上设置属性IsTabStop={TemplateBinding IsTabStop}TabIndex={TemplateBinding TabIndex},以便在控件上设置任何这些属性时,它仍然保持内部导航命令和阻止/允许使用TAB键导航到每个内部控件。