我该如何通过编程选择焦点元素?

14

有一个页面上有几个可聚焦元素(按钮、图像等),部分是在XAML中静态生成,部分是在代码后端动态生成。在这个页面上,按Tab键会使元素逐个聚焦。这意味着当前元素周围会显示虚线。现在,我想让当前聚焦的元素也被选中。这意味着要在其周围显示蓝色线条。因此,随着焦点的移动,选定的元素也会相应移动。

如何在C#代码后端实现呢?

enter image description here


你是想真的将 IsFocused 设置为 true,还是只是希望元素看起来像是被聚焦了? - Domysee
2
有些可以聚焦的项,例如网格,可能无法选择。不管怎样,您可能需要使用 FocusManager来管理所选内容。另外,由于焦点一次只能在一个控件上,因此一次只能选择一个项目。 - Kcvin
我开始觉得我们可能没有正确理解你的问题。如果我没记错,WPF中的按钮和图像没有“选定”的概念。你是不是只是想说,当焦点在你的元素(无论类型如何)上时,你想要一个蓝色的线代替虚线? - Rowbear
如果它们没有“Selected”这个概念,那么我看到的可能是它们被添加到了列表框中。 - Waterfr Villa
@WaterfrVilla 如果您想将它们添加到列表框中,我的答案是有效的。即使您正在动态构建和添加元素到代码后面的列表框中。不过,您可能需要编辑ItemContainerStyle以获得所需的蓝色边框。 - Rowbear
您的解决方案必须由代码后台完成吗? - Bruno Joaquim
5个回答

10

我认为最好的方法可能取决于您拥有哪些可聚焦元素?如果您想要针对listboxitem执行此操作,您可以仅使用xaml来执行如下操作:

<UserControl.Resources>
    <Style TargetType="ListBoxItem">
        <Style.Triggers>
            <Trigger Property="IsFocused" Value="True">
                <Setter Property="Selector.IsSelected" Value="True"></Setter>
            </Trigger>
        </Style.Triggers>
    </Style>
</UserControl.Resources>
<ListBox>
    <ListBoxItem>
        Blah
    </ListBoxItem>
</ListBox>

同样的风格触发器也可以应用于其他可聚焦和可选择的元素上。


那个页面上有几个元素。如果我在XAML文件中设置它们所有的Selector.IsSelected属性,那么哪一个会被选中?我想知道我们如何在代码背后实现这个功能? - Waterfr Villa
@WaterfrVilla 如果页面上有多个元素,则将选择当前具有焦点的元素。这不是您想要的行为吗?为什么您要特别在代码后台执行此操作?我觉得如果在xaml中完成,这是一件更加简洁的事情之一。 - Rowbear
有人给个解释吗?原问题并没有说明他想在代码后台实现。我根据原始提示回答了它。 - Rowbear
抱歉,是的那就是原因。 - Waterfr Villa

4

修改选项卡停靠点上的虚线就可以了。那个破折号表示被选中状态,所以它已经被选中了。这个“选择焦点元素”的语句没有任何意义,因为如果你正在指的是选项卡停靠点,它已经被选中了。您可以通过按Tab键,然后查看哪个按钮有点线,并按Enter键来测试它是否会执行Click事件(如果在其后面有处理程序,则会执行)。

您需要的是这个

如果您想要在代码背后完成,请将此添加到XAML资源中。

<Style x:Key="MyFocusVisual">
      <Setter Property="Control.Template">
          <Setter.Value>
              <ControlTemplate>
                   <Rectangle Margin="-2" StrokeThickness="1" Stroke="Blue" />
                </ControlTemplate>
            </Setter.Value>
        </Setter>
</Style>
....
 myButton.FocusVisualStyle = (Style)FindResource("MyFocusVisual");

如果您没有访问XAML的权限,我认为通过这个可以想到如何在代码后台添加样式并将其添加到按钮中。但是,我现在显然自相矛盾,因为您要使用代码后台,没有访问XAML是不可能的,仍然通过XAML添加比通过代码后台添加更实用。

选项卡是特殊情况。我要求其他元素,如按钮、图像等。 - Waterfr Villa

3

我会确保每个元素都是按钮或按钮的模板。这样就可以使用“IsTabStop”,或者可以将元素聚焦。 使用MrsEd的解决方案,您可以正确地为项目添加边框:

<Button x:Class="Visualisation.UserControlButtonImage"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             IsTabStop="True">
    <Button.Template>
        <ControlTemplate>
           <Grid>
               <Image/> 
           </Grid>
        </ControlTemplate>
    </Button.Template>
</Button>

2

在xml中,我将PreviewGotKeyboardFocus添加到我的窗口中。

             PreviewGotKeyboardFocus="FrmBase_OnPreviewGotKeyboardFocus"

使用 PreviewGotKeyboardFocus 在根元素(用户控件或窗口)上处理每个子控件的焦点事件。

代码后台

private void FrmBase_OnPreviewGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
    try
    {
        dynamic item = e.NewFocus;
        item.IsSelected = true;
    }
    catch (Exception ex)
    {

    }
}

1
你所指的元素类型,并非全部可选。
你需要用C#来实现,有些元素将会动态添加,键盘将通过这些元素进行切换。我建议跟踪你的焦点项目,然后实现一个方法,根据当前聚焦的元素执行任何你想要做的操作。使用键盘聚焦方法。
protected override void OnPreviewGotKeyboardFocus(KeyboardFocusChangedEventArgs e)
{
    var focusedElement = e.Source as IInputElement;
    // Do something here
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接