Deactivate FocusVisualStyle globally

2019-02-05 20:49发布

I want to globally deactivate the focus rectangles in my WPF application. For single controls that can be done via

<Style TargetType="Button">
    <Setter Property="FocusVisualStyle" Value="{x:Null}" />
</Style>

but how to apply it to all controls in my application. When applying to FrameworkElement nothing happens. What I need would be something like "apply to class x and all derived classes".

Thanks in advance,

Stefan

标签: c# wpf styles
7条回答
够拽才男人
2楼-- · 2019-02-05 21:17

This may not be simple, but you could write a function that alters the existing style of a control. Once that is written, you could write a function that recursively alters the style of each element.

查看更多
萌系小妹纸
3楼-- · 2019-02-05 21:17

You can use OverrideMetadata:

FrameworkElement.FocusVisualStyleProperty.OverrideMetadata(
    typeof(FrameworkElement),
    new FrameworkPropertyMetadata(null));
  1. you have to call this before any element is created, the Application.Startup event is probably the best place.
  2. This will only effect controls that use FrameworkElement's focus visual style and will not change controls that override it in code or styles.
  3. I haven't tries doing this with FocusVisualStyle myself
查看更多
欢心
4楼-- · 2019-02-05 21:19

I stumbled upon this as well and came up with this (indeed not very nice but effective) solution:

public class FocusVisualStyleRemover
{
  static FocusVisualStyleRemover()
  {
    EventManager.RegisterClassHandler(typeof(FrameworkElement), FrameworkElement.GotFocusEvent, new RoutedEventHandler(RemoveFocusVisualStyle), true);
  }

  public static void Init()
  {
    // intentially empty
  }

  private static void RemoveFocusVisualStyle(object sender, RoutedEventArgs e)
  {
    (sender as FrameworkElement).FocusVisualStyle = null;
  }
}

In my MainWindow's constructor I then just call FocusVisualStyleRemover.Init();

查看更多
爷、活的狠高调
5楼-- · 2019-02-05 21:23

According to http://msdn.microsoft.com/en-us/library/bb613567.aspx, you should be able to set global focus style like this:

<Style x:Key="{x:Static SystemParameters.FocusVisualStyleKey}">
  <Setter Property="Control.Template">
    <Setter.Value>
      <ControlTemplate>
        <Rectangle StrokeThickness="1"
          Stroke="Black"
          StrokeDashArray="1 2"
          SnapsToDevicePixels="true"/>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style> 

I haven't tested it, but I guess that when you empty the controltemplate, this would effectively disable the focus rectangle for the whole app (provided you include this style in app.xaml).

查看更多
冷血范
7楼-- · 2019-02-05 21:28

Part of the default Template for the Window class is an AdornerDecorator. If you override the Window's default Template to not include an AdornerDecorator, the FocusVisualStyle on all controls will not appear.

Even if a Control has a valid FocusVisualStyle that sets a Template, it will not appear without the AdornerDecorator.

An easy way to accomplish this is to include this Style in your App.xaml file under Application.Resources.

<Style TargetType="{x:Type Window}">
    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"/>
    <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Window}">
                <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
                    <ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}"/>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="ResizeMode" Value="CanResizeWithGrip">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Window}">
                        <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
                            <Grid>
                                <ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}"/>
                                <ResizeGrip x:Name="WindowResizeGrip" HorizontalAlignment="Right" IsTabStop="False" Visibility="Collapsed" VerticalAlignment="Bottom"/>
                            </Grid>
                        </Border>
                        <ControlTemplate.Triggers>
                            <MultiTrigger>
                                <MultiTrigger.Conditions>
                                    <Condition Property="ResizeMode" Value="CanResizeWithGrip"/>
                                    <Condition Property="WindowState" Value="Normal"/>
                                </MultiTrigger.Conditions>
                                <Setter Property="Visibility" TargetName="WindowResizeGrip" Value="Visible"/>
                            </MultiTrigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Trigger>
    </Style.Triggers>
</Style>
查看更多
登录 后发表回答