如何在不给键盘焦点的情况下设置逻辑焦点?

Fre*_*r38 6 wpf xaml focus focusmanager

我怎样才能在代码中定义容器或聚焦子代的逻辑焦点,而不给它键盘焦点?

我只是想控制哪个孩子会通过Tab键获得焦点或者点击没有击中孩子的容器的一部分,但是如果它还没有给它(或偷窃)实际焦点有它.

而且我还希望通过键盘手势选择特定的孩子或用鼠标点击它仍然是可能的.

我理解键盘焦点和逻辑焦点之间的WPF差异,以及对于一个元素,具有键盘焦点意味着也具有逻辑焦点的事实,但具有逻辑焦点并不意味着该元素具有键盘焦点.

我也理解附加属性FocusManager.FocusedElement定义哪个元素在可视树中具有逻辑焦点,从定义此属性的元素开始.

我已经意识到只有在FocusManager.IsFocusScope设置为true时才使用此属性,而且对于GroupBox等容器也不会使用此属性.

我已经做了很多尝试,大量的搜索和阅读WPF焦点主题,但到目前为止没有成功,我不明白我错过了什么:

  • 调用FocusManager.SetFocusedElement也给键盘焦点,我暂时将我的子元素的Focusable属性暂时更改为false,它只在第一次没有孩子聚焦之前有效,但是在孩子有焦点之后没有
  • 处理事件GotKeyboardFocusPreviewGotKeyboardFocus在元素或容器上覆盖初始聚焦元素也不起作用,因为我无法判断焦点是通过鼠标还是键盘获得的,以及焦点是直接设置为子元素还是间接通过容器.
  • 一个例子来说明我想要实现的目标:我有一组简单的RadioButtons,我想在代码中动态控制当用户将"tab"移动焦点到此GroupBox时,该选项将获得焦点(通常是选项)有isChecked=true).

    <GroupBox Header="Options" Name="myGroupBox"
              KeyboardNavigation.TabNavigation="Once" 
              KeyboardNavigation. DirectionalNavigation="Cycle" >
        <StackPanel>
            <RadioButton GroupName="g1" Name="opt1" Content="Option _1"/>
            <RadioButton GroupName="g1" Name="opt2" Content="Option _2"/>
            <RadioButton GroupName="g1" Name="opt3" Content="Option _3"/>
        </StackPanel>
    </GroupBox>
    
    Run Code Online (Sandbox Code Playgroud)

    最后一条评论,我知道如何使用ListBox实现选项的动态列表,将列表的selectedItem绑定到数据上下文的属性,然后通过ListBoxItem上的样式和模板将项目模板中的RadioButton的IsChecked属性绑定到IsSelcted它的父ListBoxItem的属性,它的工作原理,但对于我的具体情况,我需要保持我的RadioButtons直接绑定到我的数据上下文的属性,我不能同时将它们绑定到列表的IsSelected属性.

    Ric*_*d E 1

    我知道这是一个老问题,但希望这个答案能帮助其他有类似问题的人。

    如果我正确理解问题,您可以通过在 GroupBox 上设置 FocusManager.IsFocusScope="True" 来实现所需的行为,并为 RadioButton.Checked 事件连接一个事件处理程序,将逻辑焦点设置为事件的发送者:

    XML:

            <GroupBox Header="Options" Name="myGroupBox"
                  FocusManager.IsFocusScope="True"
                  RadioButton.Checked="MyGroupBox_OnChecked"
                  KeyboardNavigation.TabNavigation="Once" 
                  KeyboardNavigation.DirectionalNavigation="Cycle">
            <StackPanel>
                <RadioButton GroupName="g1" Name="opt1" Content="Option _1"/>
                <RadioButton GroupName="g1" Name="opt2" Content="Option _2"/>
                <RadioButton GroupName="g1" Name="opt3" Content="Option _3"/>
            </StackPanel>
        </GroupBox>
    
    Run Code Online (Sandbox Code Playgroud)

    背后代码:

        private void MyGroupBox_OnChecked(object sender, RoutedEventArgs e)
        {
            var radioB = sender as RadioButton;
            if (radioB != null)
                FocusManager.SetFocusedElement(myGroupBox, radioB);
        }
    
    Run Code Online (Sandbox Code Playgroud)