【问题标题】:How can I force focus into the items of an ItemsControl?如何强制将焦点集中到 ItemsControl 的项目中?
【发布时间】:2011-08-07 01:38:13
【问题描述】:

这是我的用户界面的屏幕截图。

所有内容都绑定到 Question 对象列表:

class Question
{
    public Answer[] Answers { get; set; }
    public string Text { get; set; }
}

class Answer
{
    public bool IsSelected { get; set; }
    public string Text { get; set; }
}

这是我为朋友写的一个例子,我仍然是一个相对的 MVVM 新手。 (我知道在 Answer 上使用 IsSelected 之类的 UI 概念是“不正确的”,但它的工作原理不会让朋友感到困惑。)

不管怎样,左边显然是一个ListBox,它的集合作为它的项目源。右侧是一个带有此截断 DataTemplate 的 ContentPresenter:

<DataTemplate x:Key="question" DataType="{x:Type local:Question}">
    <Grid>
        <Grid.RowDefinitions> ...  </Grid.RowDefinitions>

        <TextBlock Text="{Binding Text}" />

        <ItemsControl Grid.Row="1"
                      ItemsSource="{Binding Answers}" >
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <RadioButton Content="{Binding Text}"
                                 GroupName="Answer"
                                 IsChecked="{Binding IsSelected}"/>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </Grid>
</DataTemplate>

我已经设置了输入绑定,以便 PageUp 和 PageDown 移动问题。当问题发生变化时,我希望右侧的单选按钮之一(最好是选定的,如果有的话)成为焦点。目标是让用户使用向上/向下箭头键选择答案并使用 PageUp/PageDown 在问题之间移动。

我可以进入单选按钮并且箭头键可以工作,但是当我按空格键选择答案时,焦点会移回列表框。老实说,我完全可以不用列表框获得焦点。将 Focusable 设置为 false 似乎可以让我的焦点保持在单选按钮内,但即使我将 IsTabStop 设置为 False,Tab 键仍然可以在列表框内获得焦点。

在糟糕的旧 WinForms 中,我将有一个 SelectedIndexChanged 处理程序用于列表框,它找到第一个单选按钮并将其聚焦,以及 GotFocus 处理程序尝试像烫手山芋一样扔掉焦点。由于单选按钮是模板的一部分,因此我没有看到清晰或优雅的路径来做到这一点。我怎样才能得到我想要的行为?如果可以完成工作,“重新设计您的 UI”是一个可以接受的答案,但我希望有一个代码隐藏最少的解决方案;它让我想起了太多的 WinForms。

【问题讨论】:

    标签: wpf


    【解决方案1】:

    【讨论】:

    【解决方案2】:

    我知道你说过你不想设计 UI,但你可以让 ListBox 看起来像一个单选按钮列表。不确定 WPF 列表框是否会执行您想要的操作,但它需要和保持焦点不同,您可以设置 SelectedIndex 属性。

    【讨论】:

      【解决方案3】:

      你可以做的事情:

      <RadioButton ...
                   Loaded="RBAnswer_Loaded"/>
      
      private void RBAnswer_Loaded(object sender, RoutedEventArgs e)
      {
          var rb = (RadioButton)sender;
          var answer = (Answer)rb.DataContext;
          if (answer.IsSelected) rb.Focus();
      }
      

      (要摆脱背后的代码,您可以使用 Blend Interactivity 的 InvokeCommandAction...之类的东西将其封装在命令中)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-31
        • 2014-12-15
        • 2012-01-17
        • 1970-01-01
        • 2010-11-11
        相关资源
        最近更新 更多