开发者

WPF Gradient in 2 directions

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?


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.


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)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜