Дмитрий Штефан, преподаватель Synergy Academy, основатель IT-компании Shtefanlab, программист со стажем более 12-ти лет рассказывает и показывает, как создать blur фон текста в С#. 

Вся особенность данного метода заключается в том, что при его помощи мы можем создать красивый эффект размытия фона (например, кнопки с текстом), а само размытие будет всегда эквивалентно размеру кнопки. Другими словами, мы создадим такой стиль для кнопок, при использовании которого размытие фона текста всегда будет выглядеть адекватно и соразмерно самой кнопке независимо от размера ее текста, будь там одна буква или сто.

Для начала давайте наметим наш каркас, а именно: создадим сами кнопки внутри StackPanel. Сами кнопки вполне обычные по своему содержанию, единственное, что будет для VisualStudio (среда разработки, где создаём приложения на языке c#) не ясным на данном моменте, что мы указываем имя Template, который ещё не создан, но его написанием мы займёмся на втором этапе.

<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Button Template="{StaticResource ResourceKey=BlurButtons}" Content="IT"/>
<Button Template="{StaticResource ResourceKey= BlurButtons }" Content="Unetway"/>
<Button Template="{StaticResource ResourceKey= BlurButtons }" Content="https://unetway.com"/>
</StackPanel>

Теперь давайте займемся шаблоном. Ниже сразу привожу полный листинг кода, далее частями его разберем. Спойлер: некоторые эффекты по типу «прожатия кнопки» тоже тут есть.

<Window.Resources>
   <ControlTemplate x:Key="BlurButtons" TargetType="Button">
     <Grid Name="Btn" Height="40" Margin="20,0,0,0">
        <Border>
           <Grid>
<Label Content="{TemplateBinding Content}" Background="Transparent"        FontSize="23" VerticalAlignment="Center">
                  <Label.Style>
                     <Style TargetType="Label">
                        <Setter Property="Foreground" Value="#FF9D9999"/>
                           <Style.Triggers>
<DataTrigger Binding="{Binding Path=IsMouseOver,  ElementName=Btn}" Value="true">
                                 <Setter Property="Foreground" Value="White"/>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource = {RelativeSource Mode=FindAncestor, AncestorType={x:Type Button}}, Path = IsFocused}" Value="true">
                                 <Setter Property="Foreground" Value="White"/>
</DataTrigger>
                           </Style.Triggers>
                     </Style>
                  </Label.Style>
</Label>
<Label Content="{TemplateBinding Content}" Background="Transparent" Margin="-3,0,0,0" VerticalAlignment="Center" FontSize="23" FontWeight="Bold">
                  <Label.Style>
                     <Style TargetType="Label">
                        <Setter Property="Foreground" Value="white"/>
                        <Setter Property="Visibility" Value="Hidden"/>
                           <Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource = {RelativeSource Mode=FindAncestor, AncestorType={x:Type Button}}, Path = IsFocused}" Value="true">
                                  <DataTrigger.Setters>
                                     <Setter Property="Effect">
                                        <Setter.Value>
                                           <BlurEffect Radius="25"/>
                                        </Setter.Value>
                                     </Setter>
                                     <Setter Property="Visibility" Value="Visible"/>
                                  </DataTrigger.Setters>
</DataTrigger>
                           </Style.Triggers>
                     </Style>
                  </Label.Style>
</Label>
           </Grid>
           <Border.Style>
               <Style TargetType="Border">
                  <Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource
Mode=FindAncestor, AncestorType={x:Type Button}}, Path = IsPressed}" Value="true">
                          <Setter Property="Margin" Value="0,2,0,0"/>
                      </DataTrigger>
                  </Style.Triggers>
               </Style>
           </Border.Style>
        </Border>
     </Grid>
   </ControlTemplate>
</Window.Resources>  

Первая часть: тут просто объявляем область ресурсов, внутри которой создаем шаблон нашей будущей кнопки с нуля.

<Window.Resources>
       <ControlTemplate x:Key="BlurButtons" TargetType="Button">
           <Grid Name="Btn" Height="40" Margin="20,0,0,0">
                <Border>
                    <Grid>  

Вторая часть: создаем Label, который по сути будет основой нашей кнопки. Контент Label`а биндим на контент кнопки, который будет прописан при ее объявлении вне шаблона (в нашем случае внутри StackPanel в самом начале). 

<Label Content="{TemplateBinding Content}" Background="Transparent" FontSize="23" VerticalAlignment="Center">

Третья часть: начинается уже запутываться код, но я попробую объяснить. Мы создаем стиль нашему Label, прописываем ему цвет шрифта (сероватый оттенок). Далее объявляем пару дататриггеров. Первый будет менять цвет шрифта на белый при наведении мышкой на элемент, следующий оставлять белый шрифт, если кнопка была нажата, то есть помещена в так называемый фокус.

                  <Label.Style>
                     <Style TargetType="Label">
                        <Setter Property="Foreground" Value="#FF9D9999"/>
                           <Style.Triggers>
<DataTrigger Binding="{Binding Path=IsMouseOver,  ElementName=Btn}" Value="true">
                                 <Setter Property="Foreground" Value="White"/>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource = {RelativeSource Mode=FindAncestor, AncestorType={x:Type Button}}, Path = IsFocused}" Value="true">
                                 <Setter Property="Foreground" Value="White"/>
</DataTrigger>
                           </Style.Triggers>
                     </Style>
                  </Label.Style>
</Label>

Четвертая часть: создаем второй Label, который и хранит в себе всю магию нашего Blur эффекта. Второму Labelмы задаем также контент биндингом на контент основной кнопки (из StackPanel), фон прозрачный, отступы немного смещаем в стороны, размер шрифта делаем такой же, как и у первого Label, а вот стиль шрифта желательно задать жирный для большей наглядности. В стилях этого Label мы ему жестко прописываем цвет шрифта белый, а также вводим переменную в виде его Visibility, то есть его видимости, ей мы дальше и будем манипулировать. После объявляем триггерную область кода, где зададим всего один дататриггер. Этот дататриггер будет следить за состоянием фокуса родительского элемента (в этом случае это кнопка) и в случае положительного результата изменять свойства Label, а именно: добавит BlurEffetc с радиусом 25 и сделает этот второй Label видимым. На этом моменте Blur эффект и реализован!

<Label Content="{TemplateBinding Content}" Background="Transparent" Margin="-3,0,0,0" VerticalAlignment="Center" FontSize="23" FontWeight="Bold">
                  <Label.Style>
                     <Style TargetType="Label">
                        <Setter Property="Foreground" Value="white"/>
                        <Setter Property="Visibility" Value="Hidden"/>
                           <Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource = {RelativeSource Mode=FindAncestor, AncestorType={x:Type Button}}, Path = IsFocused}" Value="true">
                                  <DataTrigger.Setters>
                                     <Setter Property="Effect">
                                        <Setter.Value>
                                           <BlurEffect Radius="25"/>
                                        </Setter.Value>
                                     </Setter>
                                     <Setter Property="Visibility" Value="Visible"/>
                                  </DataTrigger.Setters>
</DataTrigger>
                           </Style.Triggers>
                     </Style>
                  </Label.Style>
</Label>
           </Grid>

Бонусный уровень: прописываем эффект «прожимания» кнопки. Вся магия заключается в том, что при нажатии на кнопку наш вложенный Border будет смещаться (Margin) на 2 единицы вниз. Вот и все.

<Border.Style>
               <Style TargetType="Border">
                  <Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource
Mode=FindAncestor, AncestorType={x:Type Button}}, Path = IsPressed}" Value="true">
                          <Setter Property="Margin" Value="0,2,0,0"/>
                      </DataTrigger>
                  </Style.Triggers>
               </Style>
           </Border.Style>
        </Border>
     </Grid>
   </ControlTemplate>
</Window.Resources>   

Рассмотрим еще один способ применить полученные умения. Если мы знаем, как сделать эффект размытия в текстовых визуальных элементах по типу Label, почему бы нам не добавить несколько капель фантазии и не сделать бы кнопку с эффектом неонового свечения:

(видео с демонстрацией эффекта https://disk.yandex.ru/i/7vNYFYZw7_7yEg)

В целом, с учетом вышеописанного, все должно быть понятно. Прикрепляю листинг для разбора.

   <Button  Width="150" Height="50"  Content="Shtefan">
   <Button.Style>
     <Style  TargetType="Button">
        <Setter Property="Background" Value="Transparent"/>
        <Setter Property="Foreground" Value="White"/>
        <Setter Property="FontSize" Value="24"/>
        <Setter Property="FontFamily" Value="Arial"/>
        <Setter Property="Height" Value="25"/>
        <Setter Property="FontWeight" Value="Bold"/>
        <Setter Property="BorderBrush" Value="#FF6C0BFB"/>
        <Setter Property="Template">
        <Setter.Value>
           <ControlTemplate TargetType="Button">
               <Grid>
                  <Border BorderThickness="2" BorderBrush="{TemplateBinding BorderBrush}"             CornerRadius="25" Background="{TemplateBinding Background}">
                     <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
                         <Border.Style>
                            <Style TargetType="Border">
                               <Setter Property="Visibility" Value="Hidden"/>
                                  <Style.Triggers>
                                     <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Button}}, Path = IsMouseOver}" Value="true">
                                        <DataTrigger.Setters>
                                           <Setter Property="Effect">
                                              <Setter.Value>
                                                <BlurEffect Radius="25"/>
                                              </Setter.Value>
                                            </Setter>
                                            <Setter Property="Visibility" Value="Visible"/>
                                        </DataTrigger.Setters>
                                     </DataTrigger>
                                  </Style.Triggers>
                            </Style>
                         </Border.Style>
                 </Border>
                  <Border BorderThickness="2" BorderBrush="{TemplateBinding BorderBrush}" CornerRadius="25" Background="{TemplateBinding Background}">
                     <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
                  </Border>
               </Grid>
               <ControlTemplate.Triggers>
                  <Trigger Property="IsMouseOver" Value="True">
                     <Setter Property="BorderBrush" Value="#FFA466FF"/>
                  </Trigger>
              </ControlTemplate.Triggers>
           </ControlTemplate>
        </Setter.Value>
     </Setter>
   </Style>
</Button.Style>
</Button>

 

Спасибо за внимание!