-1

我需要将按钮中使用的 VisualBrush 适合整个窗口。VisualBrush 链接到一个图像,该图像被拉伸到整个可视化,但在视觉中,该图像开始出现在按钮的角落。

        <Button x:Name="button" HorizontalAlignment="Center" VerticalAlignment="Center" Content="Acquista ora- $23.99" FontSize="48" BorderBrush="{x:Null}">
            <Button.Background>
                <VisualBrush Visual="{Binding ElementName=img}" Stretch="None" AlignmentX="Center" AlignmentY="Center" ViewboxUnits="RelativeToBoundingBox" ViewportUnits="RelativeToBoundingBox" />
            </Button.Background>
        </Button>

我能怎么做?提前致谢。

4

1 回答 1

0

如果想模糊后面的图像Button(或一般的透明控件),您必须采用不同的方法。

您需要图像的确切平铺才能使用BlurEffect.

为了不模糊Button本身,您必须在已应用的按钮下方添加一个图层BlurEffect

下面的例子扩展了一个ContentControlnamed ,它在一个元素的顶部BlurHost呈现Content例如,,实际上将使用a来模糊背景。 画笔本身有一个定义的图块,该图块位于托管(或任何其他透明控件)的位置。ButtonBorderVisualBrush
BlurHostButton

实现模糊背景的基本步骤:

  1. 添加背景图片
  2. 在元素下方创建一个模糊层
  3. 获取元素的边界,例如,相对于 Image 的父级(最好是根容器)定位的 Button
  4. 使用边界矩形来定义 VisualBrush 的平铺(图像的实际部分)
  5. 在模糊层上应用画笔

使用示例

主窗口.xaml

<Window>
  <!-- Allow the root grid to stretch accross the Window -->
  <Grid>
    <Image x:Name="img" Source="/someImage.png"  />

    <!-- 
         Optionally override the default BlurEffect 
         by setting the BlurHost.BlurEffect property 
    -->
    <local:BlurHost BlurBackground="{Binding ElementName=img}" 
                    BlurOpacity="1"
                    HorizontalAlignment="Center" 
                    VerticalAlignment="Center">
      <Button Background="Transparent" 
              FontSize="48" 
              Content="Acquista ora- $23.99" />
    </local:BlurHost>
  </Grid>
</Window>

在此处输入图像描述

实现示例

实现很简单。您必须添加属性更改处理程序才能使控件动态化。

BlurHost.cs用作容器
ContentControl模糊的背景在内容的透明区域可见。

public class BlurHost : ContentControl
{
  public Visual BlurBackground
  {
    get => (Visual)GetValue(BlurBackgroundProperty);
    set => SetValue(BlurBackgroundProperty, value);
  }

  public static readonly DependencyProperty BlurBackgroundProperty =
      DependencyProperty.Register(
        "BlurBackground",
        typeof(Visual),
        typeof(BlurHost),
        new PropertyMetadata(default(Visual), OnBlurBackgroundChanged));

  public double BlurOpacity
  {
    get => (double)GetValue(BlurOpacityProperty);
    set => SetValue(BlurOpacityProperty, value);
  }

  public static readonly DependencyProperty BlurOpacityProperty =
      DependencyProperty.Register(
        "BlurOpacity",
        typeof(double),
        typeof(BlurHost),
        new PropertyMetadata(1.0));

  public BlurEffect BlurEffect
  {
    get => (BlurEffect)GetValue(BlurEffectProperty);
    set => SetValue(BlurEffectProperty, value);
  }

  public static readonly DependencyProperty BlurEffectProperty =
      DependencyProperty.Register(
        "BlurEffect",
        typeof(BlurEffect),
        typeof(BlurHost),
        new PropertyMetadata(
          new BlurEffect() 
          { 
            Radius = 10, 
            KernelType = KernelType.Gaussian, 
            RenderingBias = RenderingBias.Performance 
          }));

  private Border PART_BlurDecorator { get; set; }
  private VisualBrush BlurDecoratorBrush { get; set; }

  static BlurHost()
  {
    DefaultStyleKeyProperty.OverrideMetadata(typeof(BlurHost), new FrameworkPropertyMetadata(typeof(BlurHost)));
  }

  public BlurHost()
  {
    Loaded += OnLoaded;

    // TODO::Update Opacity of VisualBrush when property BlurOpacity changes
    this.BlurDecoratorBrush = new VisualBrush()
    {
      ViewboxUnits = BrushMappingMode.Absolute,
      Opacity = this.BlurOpacity
    };
  }

  private void DrawBlurredElementBackground()
  {
    if (!TryFindVisualRootContainer(this, out FrameworkElement rootContainer))
    {
      return;
    }

    // Get the section of the image where the BlurHost element is located
    Rect elementBounds = TransformToVisual(rootContainer)
      .TransformBounds(new Rect(this.RenderSize));

    // Use the section bounds to actually "cut out" the image tile 
    this.BlurDecoratorBrush.Viewbox = elementBounds;
  }

  private void OnLoaded(object sender, RoutedEventArgs e)
  {
    if (TryFindVisualRootContainer(this, out FrameworkElement rootContainer))
    {
      rootContainer.SizeChanged += OnRootContainerElementResized;
    }

    DrawBlurredElementBackground();
  }

  public override void OnApplyTemplate()
  {
    base.OnApplyTemplate();
    this.PART_BlurDecorator = GetTemplateChild("PART_BlurDecorator") as Border;
    this.PART_BlurDecorator.Effect = this.BlurEffect;
    this.PART_BlurDecorator.Background = this.BlurDecoratorBrush;
  }

  private static void OnBlurBackgroundChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  {
    var this_ = d as BlurHost;
    this_.BlurDecoratorBrush.Visual = e.NewValue as Visual;
    this_.DrawBlurredElementBackground();
  }

  private void OnRootContainerElementResized(object sender, SizeChangedEventArgs e)
    => DrawBlurredElementBackground();

  private bool TryFindVisualRootContainer(DependencyObject child, out FrameworkElement rootContainerElement)
  {
    rootContainerElement = null;
    DependencyObject parent = VisualTreeHelper.GetParent(child);
    if (parent == null)
    {
      return false;
    }

    if (parent is not Window visualRoot)
    {
      return TryFindVisualRootContainer(parent, out rootContainerElement);
    }

    rootContainerElement = visualRoot.Content as FrameworkElement;
    return true;
  }
}

Generic.xaml
的默认StyleBlurHostGeneric.xaml文件位于应用程序(项目)的 Themes 文件夹中

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:Net.Wpf">

  <Style TargetType="local:BlurHost">
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="local:BlurHost">
          <Grid>

            <!-- Blur layer beneath the hosted element (ContentPresenter) -->
            <Border x:Name="PART_BlurDecorator"
                    BorderBrush="{TemplateBinding BorderBrush}"
                    BorderThickness="{TemplateBinding BorderThickness}"/>
            <ContentPresenter />
          </Grid>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
</ResourceDictionary>
于 2021-10-14T22:42:25.797 回答