3

在我目前正在处理的控件中,当一个项目获得焦点时,默认焦点矩形跨越整个行及其所有可见的子项目。我知道如何隐藏它。但是当项目具有键盘焦点时,我仍然想要这样的焦点指示器。我已经阅读了有关 IsKeyboardFocused 属性的信息,但是当鼠标单击该项目时也是如此。所以我想我需要以某种方式使用 FocusVisualStyle。但我不知道怎么做。

这是默认焦点的样子:

在此处输入图像描述

这就是它应该的样子:

在此处输入图像描述

这是我的控件模板的 XAML 代码:

<Border ...>
    <ContentPresenter FocusManager.IsFocusScope="True"
        Content="{TemplateBinding HeaderedContentControl.Header}"
        ContentTemplate="{TemplateBinding HeaderedContentControl.HeaderTemplate}"
        ContentStringFormat="{TemplateBinding HeaderedItemsControl.HeaderStringFormat}"
        ContentSource="Header"
        Name="PART_Header" .../>
</Border>
<!-- Additional border glare inside the item -->
<Border BorderThickness="1" BorderBrush="#80ffffff" Margin="1"
    SnapsToDevicePixels="True" CornerRadius="2"/>
<!-- Focus rectangle inside the item -->
<Rectangle StrokeDashArray="1 2" StrokeThickness="1" Stroke="Black"
    SnapsToDevicePixels="True" Margin="2"
    Visibility="Hidden" Name="FocusRectangle"
    FocusVisualStyle="{StaticResource FocusStyle}"/>

我的 XAML 中已经有一个默认不可见的焦点矩形。使用 FocusVisualStyle 或任何东西,它应该是可见的。但我没能做到。它要么在任何焦点处可见,要么从不可见。

4

1 回答 1

0

我找到了解决该问题的方法。对我来说看起来一样,但我不完全确定这是否是正确的方法。我从上面使用 FocusRectangle 并关心自己显示和隐藏它。

这是管理焦点矩形可见性的触发器:

<!-- Show the focus rectangle when the item is focused -->
<MultiTrigger>
  <MultiTrigger.Conditions>
    <Condition Property="Controls:TreeViewExItem.IsKeyboardMode" Value="True"/>
    <Condition Property="Controls:TreeViewExItem.IsFocused" Value="True"/>
  </MultiTrigger.Conditions>
  <Setter TargetName="FocusRectangle" Property="Visibility" Value="Visible"/>
</MultiTrigger>

然后,我向 TreeViewExItem 添加了一个新属性,该属性指示最后一次输入是来自鼠标还是键盘。这可能会扩展到触摸或手写笔,但我没有这样的设备来测试。

public static DependencyProperty IsKeyboardModeProperty =
    DependencyProperty.Register(
        "IsKeyboardMode",
        typeof(bool),
        typeof(TreeViewExItem),
        new FrameworkPropertyMetadata(false, null));

public bool IsKeyboardMode
{
    get
    {
        return (bool) GetValue(IsKeyboardModeProperty);
    }
    set
    {
        SetValue(IsKeyboardModeProperty, value);
    }
}

此属性通过绑定从父控件传递给每个项目:

<!-- Pass on the TreeViewEx' IsKeyboardMode value to each item because
  we couldn't access it otherwise in the triggers -->
<Setter Property="IsKeyboardMode"
  Value="{Binding (Controls:TreeViewEx.IsKeyboardMode),
    RelativeSource={RelativeSource
      AncestorType={x:Type Controls:TreeViewEx}}, Mode=OneWay}" />

相同的 IsKeyboardMode 属性被添加到 TreeViewEx 父控件,这就是我的魔力:

protected override void OnPreviewKeyDown(KeyEventArgs e)
{
    base.OnPreviewKeyDown(e);
    if (!IsKeyboardMode)
    {
        IsKeyboardMode = true;
        //Debug.WriteLine("Changing to keyboard mode from PreviewKeyDown");
    }
}

protected override void OnPreviewKeyUp(KeyEventArgs e)
{
    base.OnPreviewKeyDown(e);
    if (!IsKeyboardMode)
    {
        IsKeyboardMode = true;
        //Debug.WriteLine("Changing to keyboard mode from PreviewKeyUp");
    }
}

protected override void OnPreviewMouseDown(MouseButtonEventArgs e)
{
    base.OnPreviewMouseDown(e);
    if (IsKeyboardMode)
    {
        IsKeyboardMode = false;
        //Debug.WriteLine("Changing to mouse mode");
    }
}

这会对键盘和鼠标的预览事件做出反应以设置适当的输入模式。只有当最后一个输入来自键盘时,焦点矩形才可见。

于 2012-07-31T21:00:25.953 回答