WPF按钮如何决定显示FocusVisualStyle?

时间:2012-03-02 13:50:29

标签: .net wpf

我想触发Button模板的更改以补充FocusVisualStyle效果。基本上我希望下面代码段中的文字'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>

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

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

查看框架的源代码我没有看到任何特殊内容:KeyboardNavigation.ShowFocusVisual()按预期调用FrameworkElement.OnGotKeyboardFocus()。但是,显然必须有其他事情发生,因为不是每个gotKeyboardFocus事件都会导致FocusVisualStyle显示。

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

3 个答案:

答案 0 :(得分:1)

愚蠢的问题可能,但为什么不简单地复制FocusVisualStyle(在Blend中)并编辑它以显示你想要的东西?这就是我们通常做这些事情的方式。

干杯, 劳伦

答案 1 :(得分:0)

而不是使用IsKeyboardFocused尝试IsFocused

答案 2 :(得分:0)

是通过在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); }
}

然后在控制模板中...

     <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>