Wpf вокруг странной границы - PullRequest
4 голосов
/ 27 августа 2011

enter image description here

Привет

Уже более 2 дней я пытаюсь создать кнопку переключения, которая находится в нажатом состоянии, как на изображении выше, но эта верхняя граница вызывает у меня головную боль. Кто-нибудь знает, как создать этот круглый угол, который идет вниз? Фон представляет собой линейный градиент сверху вниз: # b8c7d6 - # a8b3c4

Любая помощь будет принята с благодарностью !!

У меня есть что-то вроде этого, но это далеко от дизайна:

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

Ответы [ 2 ]

4 голосов
/ 02 августа 2012

Вот что хорошо сработало для меня. Я обнаружил, что закругленные углы добавили некоторые дополнительные проблемы с правильным созданием тени верхней области, но я смог добиться этого, комбинируя несколько приемов.

первая техника предполагает умное использование двух границ. Для внешней границы ClipToBounds установлено значение true, а для внутренней границы DropShadowEffect, для ShadowDepth установлено значение 0 и BlurRadius около 5. Это дает нам часть того, что нам нужно, но не решает проблему закругленных углов (мы вернемся к этому). Эту технику можно найти на этой статье . Вот суть этого:

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

Если я правильно помню, в этот момент у нас будет что-то близкое к тому, что вы хотите, за исключением того, что DropShadowEffect «кровоточит» из закругленных углов (опять же, мы скоро это рассмотрим).

Другая проблема, с которой мы столкнулись бы сейчас, заключается в том, что к любым дочерним элементам, которые мы помещаем во внутренний Border, также будет применен DropShadowEffect! Чтобы исправить эту проблему, нам понадобится вторая техника . Поместите два Borders вместе с другим контейнером (для хранения вашего содержимого) в Grid, чтобы внешний Border и новый контейнер были братьями и сестрами. Это заставит братьев и сестер перекрывать друг друга, применяя только DropShadowEffect к Border. См. этот ответ .

Теперь обратимся к проблеме «кровотечения», когда DropShadowEffect не следует контуру закругленных углов, а действует так, как если бы углы были прямыми. Для этого требуется третий метод . Нам нужно использовать пользовательский элемент управления Михаэля ClippingBorder . Нам нужно заменить вышеупомянутый внешний Border элемент управления его ClippingBorder, сохраняя для ClipToBounds значение true. Это урежет кровотечение на закругленных углах.

Мне удалось объединить эти три метода , чтобы создать "утопленный" (или "вставленный") вид границы. Это выглядело примерно так:

<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

Обратите внимание, что верхний "свет" (DropShadowEffect) хорошо повторяет контур закругленного угла границы:

Sunk-in border glow follow contour of the rounded corner

0 голосов
/ 27 августа 2011

Я бы использовал две границы: внешняя будет выглядеть примерно так:

<Border CornerRadius="3" BorderBrush="White" BorderThickness="1">

Внутренняя сторона создаст эффект тени следующим образом:

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

Очевидно, вам нужноотрегулируйте значения, но это должно как минимум произвести эффект, который вы хотите.

...