Tar
Tar

Reputation: 9015

How to make an element look like it's "below" the border, but "above" the border's content, when the border has rounded corners?

TL/DR:

How to make an element look like it's "below" the border, but "above" the border's content, when the border has rounded corners?

Elaboration:

This is what I'm trying to accomplish: when the mouse moves into the border, a "curtain" is drawn from the top-left corner until it covers either the whole border's content or maybe just 3/4 of it, like this example:

enter image description here

This "curtain" is intended to carry additional controls to update its box content.

I'm stuck right now creating the red path - I can't make it perfectly aligned along the black border, so it'll look like it comes from below the border, but above its content.

Here is the XAML I currently have:

<UserControl x:Class="FamilyTree.GroupBox"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="100" d:DesignWidth="100">
    <Grid>
        <StackPanel Orientation="Horizontal" VerticalAlignment="Center">
            <StackPanel.Resources>
                <Style TargetType="{x:Type TextBlock}">
                    <Style.Setters>
                        <Setter Property="VerticalAlignment" Value="Center" />
                    </Style.Setters>
                </Style>
            </StackPanel.Resources>

            <Border CornerRadius="5" BorderBrush="Black" BorderThickness="1" VerticalAlignment="Center" ToolTip="{Binding ToolTipString}" Background="White">
                <Grid>
                    <StackPanel Margin="3">
                        <StackPanel.Resources>
                            <Style TargetType="{x:Type Border}">
                                <Setter Property="CornerRadius" Value="3" />
                                <Setter Property="BorderBrush" Value="Blue" />
                                <Setter Property="BorderThickness" Value="0.6" />
                                <Setter Property="VerticalAlignment" Value="Center" />
                                <Setter Property="Padding">
                                    <Setter.Value>
                                        <Thickness Right="2" />
                                    </Setter.Value>
                                </Setter>
                                <Setter Property="Margin" Value="0" />
                            </Style>
                        </StackPanel.Resources>
                        <StackPanel Orientation="Horizontal">
                            <Border>
                                <TextBlock Text="Name" />
                            </Border>
                            <TextBlock Text="/"/>
                            <Border>
                                <TextBlock Text="Family" />
                            </Border>
                        </StackPanel>
                        <TextBlock Text="Group"/>
                    </StackPanel>
                    <Path Stroke="Red" Fill="Red" Data="M50,0 L5,0 C1.5,0 0,1.5 0,5 L0,50" StrokeLineJoin="Round" Margin="0.5"/>
                </Grid>
            </Border>
        </StackPanel>
    </Grid>
</UserControl>

Upvotes: 7

Views: 176

Answers (1)

Chris W.
Chris W.

Reputation: 23270

If it were me. I would use a LinearGradient animation to fill your Border without using another object like a Path to accomplish this effect. So as just a quick and sloppy example. Something like this;

Our Storyboard to control the StartPoint/EndPoint of the Gradient to bring it in from an angle;

<Storyboard x:Key="Curtain">
   <DoubleAnimationUsingKeyFrames 
                       Storyboard.TargetProperty="(Panel.Background).(GradientBrush.GradientStops)[1].(GradientStop.Offset)"                                                                          
                       Storyboard.TargetName="border">
      <EasingDoubleKeyFrame KeyTime="0:0:1" Value="1"/>
    </DoubleAnimationUsingKeyFrames>
    <DoubleAnimationUsingKeyFrames 
                       Storyboard.TargetProperty="(Panel.Background).(GradientBrush.GradientStops)[0].(GradientStop.Offset)"                                                                          
                       Storyboard.TargetName="border">
       <EasingDoubleKeyFrame KeyTime="0:0:1" Value="1"/>
     </DoubleAnimationUsingKeyFrames>
</Storyboard>

Then our Border;

<Border x:Name="border" BorderBrush="Blue" BorderThickness="1" Height="200" Width="350">
   <Border.Background>
      <LinearGradientBrush EndPoint="0.964,0.992" StartPoint="0.017,0.019">
         <GradientStop Color="#FFF90202" Offset="0"/>
         <GradientStop Offset="0.001"/>
      </LinearGradientBrush>
   </Border.Background>             
</Border>

This way, it won't matter if your CornerRadius is set, or if you wanted to get fancy, you could do the same on any shape or Path no matter of it's Geometry and it will spread the area evenly while it performs the animation. However the Border would need a higher z-index or lower placement in the DOM to render over the top of the content.

You'll probably want to tweak the values on your StartPoint/EndPoint and KeyTime to get exactly what you want, but this was just a quick 60sec example to convey the concept.

Hope this helps, cheers!

Upvotes: 1

Related Questions