【问题标题】:Deactivate FocusVisualStyle globally全局停用 FocusVisualStyle
【发布时间】:2010-11-06 12:58:45
【问题描述】:

我想在我的 WPF 应用程序中全局停用焦点矩形。对于可以通过

完成的单个控件
<Style TargetType="Button">
    <Setter Property="FocusVisualStyle" Value="{x:Null}" />
</Style>

但是如何将它应用到我的应用程序中的所有控件。当应用到 FrameworkElement 时,什么也没有发生。我需要的是“适用于 x 类和所有派生类”。

提前致谢,

斯蒂芬

【问题讨论】:

    标签: c# wpf styles


    【解决方案1】:

    我也偶然发现了这个并想出了这个(确实不是很好但有效)的解决方案:

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

    然后在我的 MainWindow 的构造函数中调用 FocusVisualStyleRemover.Init();

    【讨论】:

      【解决方案2】:

      Window 类的默认Template 的一部分是AdornerDecorator。如果您覆盖Window 的默认Template 以不包含AdornerDecorator,则所有控件上的FocusVisualStyle 都不会出现。

      即使Control 具有设置Template 的有效FocusVisualStyle,如果没有AdornerDecorator,它也不会出现。

      实现此目的的一种简单方法是将此Style 包含在Application.Resources 下的App.xaml 文件中。

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

      【讨论】:

        【解决方案3】:

        根据http://msdn.microsoft.com/en-us/library/bb613567.aspx,您应该可以像这样设置全局焦点样式:

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

        我还没有测试过,但我猜当你清空控件模板时,这将有效地禁用整个应用程序的焦点矩形(假设你在 app.xaml 中包含此样式)。

        【讨论】:

          【解决方案4】:
          【解决方案5】:

          我知道这听起来很乏味,但您可能必须对所有其他控件类型单独执行相同的操作。不过,列出它们并执行几个简单的查找/替换操作应该可以满足您的需求。

          【讨论】:

            【解决方案6】:

            您可以使用 OverrideMetadata:

            FrameworkElement.FocusVisualStyleProperty.OverrideMetadata(
                typeof(FrameworkElement),
                new FrameworkPropertyMetadata(null));
            
            1. 您必须在创建任何元素之前调用它,Application.Startup 事件可能是最好的地方。
            2. 这只会影响使用 FrameworkElement 的焦点视觉样式的控件,不会更改在代码或样式中覆盖它的控件。
            3. 我自己没有尝试用 FocusVisualStyle 做这个

            【讨论】:

            • 不幸的是,这会导致“PropertyMetadata 已为类型‘FrameworkElement’注册
            • “对 OverrideMetadata 的调用只能在提供自身作为此方法的 forType 参数的类型的静态构造函数中执行,或者通过类似的实例化执行。” msdn.microsoft.com/en-us/library/ms597491.aspx
            【解决方案7】:

            这可能并不简单,但您可以编写一个函数来改变控件的现有样式。编写完成后,您可以编写一个递归更改每个元素样式的函数。

            【讨论】:

            • 可能是因为它不必要地复杂,充满了困难,例如确保您已经涵盖了所有可能的边缘情况并且很难维护,仅举2个例子。与StyleSetter相比对于每种类型(虽然乏味,但很简单),您的建议听起来很疯狂。我没有给 -1。
            • 由于他没有评论任何解决方案将起作用,我们不知道其他想法是否有帮助。如果这是满足他需求的唯一想法,“疯狂”将是一个不准确的描述。
            猜你喜欢
            • 2013-09-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-05-21
            • 1970-01-01
            • 1970-01-01
            • 2011-06-16
            • 1970-01-01
            相关资源
            最近更新 更多