WPF 2 个方向的渐变

发布于 2024-10-06 11:58:54 字数 724 浏览 1 评论 0原文

如果我想让列表框中所选项目的边缘看起来平滑,我会这样做:

<Setter Property="Background" TargetName="Bd">
     <Setter.Value>
         <LinearGradientBrush EndPoint="0,0" StartPoint="1,0">
           <GradientStop Offset="0" Color="Transparent"/>
           <GradientStop Offset="0.05" Color="{x:Static SystemColors.HighlightColor}"/>
           <GradientStop Offset="0.95" Color="{x:Static SystemColors.HighlightColor}"/>
           <GradientStop Offset="1" Color="Transparent"/>
         </LinearGradientBrush>
     </Setter.Value>
 </Setter>

但是,这只会使左侧和右侧边缘平滑,而不是顶部和底部。如果我更改 StartPoint 和 EndPoint,我可以使顶部和底部平滑,但随后我会失去左侧和右侧的平滑度。那么如何使用渐变画笔使所有 4 个边框变得平滑呢?

If i want to make the edges of a selected item in a Listbox look smooth I do this:

<Setter Property="Background" TargetName="Bd">
     <Setter.Value>
         <LinearGradientBrush EndPoint="0,0" StartPoint="1,0">
           <GradientStop Offset="0" Color="Transparent"/>
           <GradientStop Offset="0.05" Color="{x:Static SystemColors.HighlightColor}"/>
           <GradientStop Offset="0.95" Color="{x:Static SystemColors.HighlightColor}"/>
           <GradientStop Offset="1" Color="Transparent"/>
         </LinearGradientBrush>
     </Setter.Value>
 </Setter>

However, this only makes the left and right edge smooth, not the top and bottom. If I change StartPoint and EndPoint, I can make the top and bottom smooth, but then I loose the smoothness on the left&right sides. So how can I make all 4 borders smooth using a Gradient brush?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

芯好空 2024-10-13 11:58:54

正如其他人已经建议的那样,OpacityMask 是实现此目的的一种方法,但它有点具有挑战性,因为您无法在画笔上设置 OpacityMask。您只能在视觉对象上设置它 - OpacityMask 是在每个视觉对象的基础上完成的。但是 ListBoxBackground 并不是可视化树中的单独元素 - 它只是 ListBox 的一个属性,而且通常是模板绑定到模板中某处的诸如 Border 元素之类的内容。

对于一些人在这里建议的位图效果的使用也是如此 - 这些也适用于整个视觉效果,而不是单个画笔。

但是,您可以使用 VisualBrush 来处理此问题 - 它允许您使用可视化树定义画笔。所以我认为这大致符合您的要求:

<Setter Property="Background" TargetName="Bd">
  <Setter.Value>
    <VisualBrush>
      <VisualBrush.Visual>
        <Rectangle Width="1" Height="1">
          <Rectangle.Fill>
            <LinearGradientBrush EndPoint="0,0" StartPoint="1,0">
              <GradientStop Offset="0" Color="Transparent"/>
              <GradientStop Offset="0.05" Color="{x:Static SystemColors.HighlightColor}"/>
              <GradientStop Offset="0.95" Color="{x:Static SystemColors.HighlightColor}"/>
              <GradientStop Offset="1" Color="Transparent"/>
            </LinearGradientBrush>
          </Rectangle.Fill>
          <Rectangle.OpacityMask>
            <LinearGradientBrush EndPoint="0,0" StartPoint="0,1">
              <GradientStop Offset="0" Color="Transparent"/>
              <GradientStop Offset="0.05" Color="White"/>
              <GradientStop Offset="0.95" Color="White"/>
              <GradientStop Offset="1" Color="Transparent"/>
            </LinearGradientBrush>
          </Rectangle.OpacityMask>
        </Rectangle>
      </VisualBrush.Visual>
    </VisualBrush>
  </Setter.Value>
</Setter>

虽然角落可能不完全符合您的要求 - 取决于它们最终有多大。当你使用这种技术时,它们看起来并不特别圆。所以你可以沿着效果路线走。您可能更喜欢这样:

<Setter Property="Background" TargetName="Bd">
  <Setter.Value>
    <VisualBrush Viewbox="0.1,0.1,0.8,0.8">
      <VisualBrush.Visual>
        <Border Width="100" Height="100" CornerRadius="10"
             Background="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}">
          <Border.Effect>
            <BlurEffect Radius="20"/>
          </Border.Effect>
        </Border>
      </VisualBrush.Visual>
    </VisualBrush>
  </Setter.Value>
</Setter>

请注意,我使用了 Effect 而不是 BitmapEffectEffect 的选项较少,但它们通常是更好的选择,因为它们被设计为在硬件中渲染。

The OpacityMask is one way to do this, as others have already suggested, but it's slightly challenging because you cannot set an OpacityMask on a brush. You can only set it on a visual - OpacityMask is something that is done on a per-visual basis. But the Background of a ListBox isn't a separate element in the visual tree - it's just a property of the ListBox, and it's usually template bound to something like a Border element somewhere in the template.

Same goes for the use of bitmap effects that some people have suggested here - those are also applied to whole visuals, not to individual brushes.

However, you can handle this with a VisualBrush - that lets you define a brush by using a visual tree. So I think this does roughly what you're looking for:

<Setter Property="Background" TargetName="Bd">
  <Setter.Value>
    <VisualBrush>
      <VisualBrush.Visual>
        <Rectangle Width="1" Height="1">
          <Rectangle.Fill>
            <LinearGradientBrush EndPoint="0,0" StartPoint="1,0">
              <GradientStop Offset="0" Color="Transparent"/>
              <GradientStop Offset="0.05" Color="{x:Static SystemColors.HighlightColor}"/>
              <GradientStop Offset="0.95" Color="{x:Static SystemColors.HighlightColor}"/>
              <GradientStop Offset="1" Color="Transparent"/>
            </LinearGradientBrush>
          </Rectangle.Fill>
          <Rectangle.OpacityMask>
            <LinearGradientBrush EndPoint="0,0" StartPoint="0,1">
              <GradientStop Offset="0" Color="Transparent"/>
              <GradientStop Offset="0.05" Color="White"/>
              <GradientStop Offset="0.95" Color="White"/>
              <GradientStop Offset="1" Color="Transparent"/>
            </LinearGradientBrush>
          </Rectangle.OpacityMask>
        </Rectangle>
      </VisualBrush.Visual>
    </VisualBrush>
  </Setter.Value>
</Setter>

The corners might not be quite what you're looking for though - depends on how big they end up being. They don't look especially round when you use this technique. So you could go down the effect route. You might prefer this:

<Setter Property="Background" TargetName="Bd">
  <Setter.Value>
    <VisualBrush Viewbox="0.1,0.1,0.8,0.8">
      <VisualBrush.Visual>
        <Border Width="100" Height="100" CornerRadius="10"
             Background="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}">
          <Border.Effect>
            <BlurEffect Radius="20"/>
          </Border.Effect>
        </Border>
      </VisualBrush.Visual>
    </VisualBrush>
  </Setter.Value>
</Setter>

Note that I've used an Effect rather than a BitmapEffect. You have fewer options with Effect, but they're usually a better option as they're designed to render in hardware.

深陷 2024-10-13 11:58:54

我不认为使用内置的渐变画笔可以做到这一点。 你可以实现自己的RectangleGradientBrush,但我认为这并不容易......(实际上这似乎不可能,因为Brush实现依赖于用户代码无法访问的低级渲染内容)

I don't think it can be done with the built-in gradient brushes. You could implement your own RectangleGradientBrush, but I don't think it's easy... (actually it doesn't seem possible, as Brush implementations depend on low level rendering stuff that's not accessible from user code)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文