Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wpf round weird border

Tags:

border

wpf

enter image description here

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

                    <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>
like image 331
Narcis Avatar asked Aug 27 '11 16:08

Narcis


1 Answers

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>

Sunk-in border results

Notice that the upper "glow" (DropShadowEffect) nicely follows the contour of the rounded corner of the Border:

Sunk-in border glow follow contour of the rounded corner

like image 75
Jason Frank Avatar answered Sep 25 '22 23:09

Jason Frank