Wpf round weird border
Hi
I'm trying for over 2 days now to create toggle button that in pressed state like the above image, but that upper border is giving me a headache. Does anyone have any idea how to create that round corner that goes down? The background is a linear gradient top to bottom: #b8c7d6 - #a8b3c4
Any help at all would be greatly appreciated!!
I have something like this but it is far from the design:
<Style x:Key="ToggleButtonStyle" TargetType="{x:Type ToggleButton}">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Grid>
<Border Background="Black" BorderThickness="1" BorderBrush="#FF4E4F50" CornerRadius="3"/>
<Border Background="Black" Margin="1" CornerRadius="3"/>
<Border Margin="2" CornerRadius="3">
<Border.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#0099B9D1" Offset="0"/>
<GradientStop Color="#FF99B9D1" Offset="1"/>
<GradientStop Color="#B299B9D1" Offset="0.054"/>
</LinearGradientBrush>
</Border.Background>
</Border>
<Border Margin="2" CornerRadius="3" Opacity="0.3">
<Border.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<LinearGradientBrush.RelativeTransform>
<TransformGroup>
<ScaleTransform CenterY="0.5" CenterX="0.5"/>
<SkewTransform CenterY="0.5" CenterX="0.5"/>
<RotateTransform Angle="90" CenterY="0.5" CenterX="0.5"/>
<TranslateTransform/>
</TransformGroup>
</LinearGradientBrush.RelativeTransform>
<GradientStop Color="Black" Offset="0"/>
<GradientStop Color="Black" Offset="1"/>
<GradientStop Color="#00090909" Offset="0.022"/>
<GradientStop Color="#00000000" Offset="0.99"/>
<GradientStop Color="#45060606" Offset="0.001"/>
</LinearGradientBrush>
</Border.Background></Borde开发者_C百科r>
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsKeyboardFocused" Value="true">
</Trigger>
<Trigger Property="IsChecked" Value="true">
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="#ADADAD"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Here's what worked well for me. I found that the rounded corners added some additional challenges with creating the top area shadow correctly, but I was able to get that working by combining several techniques.
The first technique involves the clever use of two Borders. The outer border has its ClipToBounds
set to true, and the inner Border has a DropShadowEffect
, with ShadowDepth
set to 0 and a BlurRadius
of around 5. This gets us part of what we need, but it won't handle the rounded corner issue (we'll get to that). This technique can be found at this article. Here's the gist of it:
<Border BorderBrush="DarkGray" BorderThickness="1" ClipToBounds="True">
<Border BorderBrush="Black" BorderThickness="1" Margin="-1">
<Border.Effect>
<DropShadowEffect ShadowDepth="0" BlurRadius="6">
</Border.Effect>
</Border>
</Border>
If I recall correctly, at this point we would have something close to what you want, except that the DropShadowEffect
"bleeds" out of the rounded corners (again we'll address that soon).
Another problem we would now have is that any child elements that we place inside the inner Border
would also have the DropShadowEffect
applied to them! To correct that problem, we need the second technique. Place the two Borders
, along with another container (to hold your content) into a Grid
, so that the outer Border
and the new container are siblings. This will cause the siblings to overlap each other, while only applying the DropShadowEffect
to the Border
. See this answer.
Now to address the "bleed" issue, where the DropShadowEffect
does not follow the contour of the rounded corners, but rather acts as if the corners were straight. This requires the third technique. We need to use Michah's ClippingBorder custom control. We need to replace the above-mentioned outer Border
control with his ClippingBorder
, still keeping ClipToBounds
set to true. This will trim off the bleed at the rounded corners.
I was able to combine these three techniques to create a "sunk in" (or "inset") border look. It looked something like:
<Grid>
<local:ClippingBorder x:Name="TopShadowClippingBorder"
BorderThickness="0"
CornerRadius="5"
ClipToBounds="True">
<Border x:Name="TopShadowBorder"
BorderBrush="#D8333333" BorderThickness=".5,1,.5,0"
Padding="0"
CornerRadius="5"
ClipToBounds="True">
<Border.Effect>
<DropShadowEffect Direction="270" ShadowDepth="0.5"/>
</Border.Effect>
</Border>
</local:ClippingBorder>
<Border x:Name="InsetBorder"
BorderBrush="#99A1A1A1" BorderThickness="0.5,0,0.5,1"
CornerRadius="5" />
<StackPanel x:Name="Contents_StackPanel" Orientation="Horizontal" Margin="5,5,5,5">
(Contents go here...)
</StackPanel>
</Grid>
Notice that the upper "glow" (DropShadowEffect) nicely follows the contour of the rounded corner of the Border:
I would use two borders: the outer would look something like:
<Border CornerRadius="3" BorderBrush="White" BorderThickness="1">
The inner would create the shadow effect as follows:
<Border CornerRadius="3" BorderThickness="2,4,2,0">
<Border.BorderBrush>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="Black"/>
<GradientStop Offset="0.2" Color="#00000000"/>
</LinearGradientBrush>
</Border.BorderBrush>
Obviously you'll need to tweak the values, but that should at least produce the effect you're after.
精彩评论