【问题标题】:How do WPF buttons decide to show FocusVisualStyle?WPF 按钮如何决定显示 FocusVisualStyle?
【发布时间】:2012-03-02 13:50:29
【问题描述】:

我想触发 Button 模板的更改以补充 FocusVisualStyle 效果。基本上我希望下面 sn-p 中的文本“foo”变成红色当且仅当 FocusVisualStyle 可见:

<Style x:Key="ButtonStyle1" TargetType="{x:Type Button}">
    <Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Grid>
                    <ContentPresenter/>
                    <TextBlock x:Name="TxtFoo" Text="foo" Foreground="Black"/>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsKeyboardFocused" Value="true">
                        <Setter Property="Foreground" TargetName="TxtFoo" Value="Red"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

请忽略这个例子是愚蠢的事实,实际代码更有用(它修改了一个路径)。

这适用于键盘导航,但有一个问题:按下按钮时文本也会变为红色(在这种情况下不显示 FocusVisualStyle)。在 GotKeyboardFocus/LostKeyboardFocus 上使用 eventTrigger 会产生相同的结果。

查看框架的源代码,我没有看到任何特别之处:KeyboardNavigation.ShowFocusVisual() 按预期由FrameworkElement.OnGotKeyboardFocus() 调用。但是,显然肯定有其他事情发生,因为并非每个 gotKeyboardFocus 事件都会导致 FocusVisualStyle 显示。

如果我想与 FocusVisualStyle“同步”,我应该定位哪些属性/事件?

【问题讨论】:

    标签: .net wpf


    【解决方案1】:

    也许是个愚蠢的问题,但您为什么不简单地复制 FocusVisualStyle(在 Blend 中)并对其进行编辑以显示您想要的内容?这是我们通常做这些事情的方式。

    干杯, 洛朗

    【讨论】:

    • 我不能使用 FocusVisualStyle,因为它会在按钮上放置一个附加层(默认模板只是虚线边框)。 FocusVisualStyle 中的所有设置器都以该附加层为目标。但是,在这种情况下,我必须与控件本身进行交互。在示例中,'foo' 是硬连线的,实际上我更改了实际按钮的内容。这有意义吗?
    • 我明白了。我现在不能尝试,但在 Blend 中打开 Button 控件模板并检查 Visual States 或 Triggers。找到专注的人,并检查他们在模板中的作用。恕我直言,最好的方法是有两层,当聚焦时隐藏内容一层并显示焦点一层。有意义吗?
    • 有道理。 wpf 模板仍然不是基于视觉状态管理器的,但这样做并不难(可能从 Silverlight 模板开始)。感谢您的提示!
    • 尝试失败:基于 VSM 的模板(如 Silverlight 中的默认模板)有同样的问题:当您按下按钮时它也会进入 Focused 状态(没有键盘导航)。
    【解决方案2】:

    而不是使用IsKeyboardFocused 尝试IsFocused

    【讨论】:

    • IsFocused 和 IsKeyboardFocused 都不跟踪焦点视觉对象的状态。当您单击控件时,它们都返回 true,而 Focus 视觉对象仅在您使用键盘导航到控件时显示,而不是在您使用鼠标单击控件时显示。 (视觉状态也有同样的问题)
    【解决方案3】:

    通过翻阅 Wpf 的 .net 核心资源找到,但它也适用于 WPF 4.7.2....

    对于普通控件,仅当键盘是最近的输入设备时才应用FocusVisualStyle。不幸的是,没有办法让FocusVisualStyle 依赖于它所应用的控件的状态。并且没有开箱即用的属性、事件或附加属性可用于检测FocusVisualStyle 状态。

    解决方案是在你的控件上提供一个派生的依赖属性,然后在控件模板中使用触发器模拟 FocusVisualStyle。

    在您的控件中包含以下代码,并在您的控件模板中触发IsVisualFocus 属性,这仅在应用了FocusVisualStyle 时才成立。

    protected override void OnGotFocus(RoutedEventArgs e)
    {
        base.OnGotFocus(e);
        IsVisualFocus = IsKeyboardMostRecentInputDevice();
    }
    
    protected override void OnLostFocus(RoutedEventArgs e)
    {
        base.OnLostFocus(e);
        IsVisualFocus = false;
    }
    
    private bool IsKeyboardMostRecentInputDevice()
    {
        return InputManager.Current.MostRecentInputDevice is KeyboardDevice;
    }
    
    public bool IsVisualFocus
    {
        get { return (bool)GetValue(IsVisualFocusProperty); }
        set { SetValue(IsVisualFocusProperty, value); }
    }
    

    然后在 Control 模板中...

         <Style x:Key="{x:Type local:FlatButton}" TargetType="local:FlatButton">
              <Setter Property="FocusVisualStyle" Value={x:Null}/> <!-- disable system FocusVisualStyle -->
              <Setter Property="Template">
                    <Setter.Value>
                            <ControlTempalte.Triggers>
                                  <Trigger Property="IsVisualFocus" Value="True">
                                           .... your setters here ....
                                           <Setter TargetName="T_Border" Property="Background" Value="#10FF0000"/>
                                  </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>          
                    </Setter.Value>
              </Setter>
       </Style>
    

    【讨论】:

      猜你喜欢
      • 2013-05-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-17
      • 2013-03-25
      • 1970-01-01
      • 2015-10-13
      • 2012-04-23
      相关资源
      最近更新 更多