将焦点矩形应用于子元素

时间:2012-07-26 10:13:09

标签: wpf xaml focus

在我正在处理的控件中,当项目被聚焦时,默认焦点矩形跨越整个行及其所有可见子项。我知道如何隐藏它。但是当项目具有键盘焦点时,我仍然需要这样的焦点指示器。我已经了解了IsKeyboardFocused属性,但是当鼠标单击该项时也是如此。所以我想我需要以某种方式使用FocusVisualStyle。但我无法弄清楚如何。

这是默认焦点的样子:

enter image description here

这就是它应该的样子:

enter image description here

这是我的控件模板的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或任何东西,它应该是可见的。但我没有设法做到这一点。它可以在任何焦点上显示,也可以从不显示。

1 个答案:

答案 0 :(得分: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");
    }
}

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