Поделиться через


Пошаговое руководство. Создание кнопки с помощью XAML

Это пошаговое руководство предназначено для изучения того, как с помощью XAML можно создать анимированную кнопку для использования в приложении Windows Presentation Foundation. В этом пошаговом руководстве для создания ресурса настраиваемой кнопки используются стили и шаблон, что обеспечивает повторное использование кода и разделение логики кнопки от объявления кнопки. Код в этом пошаговом руководстве полностью написан на языке XAML.

Внимание

В этом пошаговом руководстве показано, как можно создать приложение путем ввода или копирования и вставки кода на языке XAML в Visual Studio. Если вы хотите узнать, как для создания того же приложения использовать конструктор, см. статью Создание кнопки с помощью Microsoft Expression Blend.

На следующем рисунке показаны готовые кнопки.

Пользовательские кнопки, созданные с помощью XAML

Создание основных кнопок

Начнем с создания проекта и добавления нескольких кнопок в окно.

Создание проекта WPF и добавление кнопок в окно

  1. Запустите Visual Studio.

  2. Создайте новый проект WPF: в меню Файл нажмите сначала пункт Создать, а затем Проект. Найдите шаблон Приложение Windows (WPF) и назначьте проекту имя «AnimatedButton». В результате будет создана основная структура для приложения.

  3. Добавьте основные кнопки по умолчанию: Все файлы, необходимые для этого пошагового руководства, предоставляются шаблоном. Откройте файл Window1.xaml, дважды щелкнув его в Обозревателе решений. По умолчанию в файле Window1.xaml есть элемент Grid. Удалите элемент Grid и добавьте несколько кнопок на страницу XAML, введя или вставив следующий фрагмент кода в файл Window1.xaml:

    <Window x:Class="AnimatedButton.Window1"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      Title="AnimatedButton" Height="300" Width="300"
      Background="Black">
      <!-- Buttons arranged vertically inside a StackPanel. -->
      <StackPanel HorizontalAlignment="Left">
          <Button>Button 1</Button>
          <Button>Button 2</Button>
          <Button>Button 3</Button>
      </StackPanel>
    </Window>
    

    Нажмите клавишу F5, чтобы запустить приложение; вы увидите набор кнопок, как это представлено на следующем рисунке.

    Три основные кнопки

    Теперь, после создания основных кнопок, можно завершить работу с файлом Window1.xaml. Дальше в этом пошаговом руководстве основное внимание уделяется файлу app.xaml, в котором определяются стили и шаблон кнопок.

Задание основных свойств

Давайте настроим некоторые свойств этих кнопок, чтобы осуществить управление их внешним видом и макетом. Вместо того, чтобы настраивать свойства кнопок по отдельности, нужно использовать ресурсы для определения свойств кнопок во всем приложении. Ресурсы приложений концептуально похожи на внешние каскадные таблицы стилей (CSS) для веб-страниц; однако ресурсы намного эффективней каскадных таблицы стилей (CSS), в чем можно будет убедиться в конце этого пошагового руководства. Дополнительные сведения о ресурсах см. в разделе Ресурсы XAML.

Использование стилей для задания основных свойств кнопок

  1. Определите блок Application.Resources: откройте файл app.xaml и добавьте следующий выделенный фрагмент разметки, если он еще отсутствует в этом файле:

    <Application x:Class="AnimatedButton.App"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      StartupUri="Window1.xaml"
      >
      <Application.Resources>
        <!-- Resources for the entire application can be defined here. -->
      </Application.Resources>
    </Application>
    

    Область ресурса определяется тем, где определяется ресурс. Определение ресурсов в Application.Resources в файле app.xaml позволяет использовать ресурсы в любом месте приложения. Дополнительные сведения об определении области ресурсов см. в статье Ресурсы XAML.

  2. Создайте стиль и определите с его помощью базовые значения свойств: добавьте следующую разметку в блок Application.Resources. Эта разметка создает объект Style, который применяется ко всем кнопкам в приложении и задает для свойства кнопок Width значение 90 и для свойства Margin значение 10:

    <Application.Resources>
      <Style TargetType="Button">
        <Setter Property="Width" Value="90" />
        <Setter Property="Margin" Value="10" />
      </Style>
    </Application.Resources>
    

    Свойство TargetType определяет то, что стиль применяется ко всем объектам типа Button. Каждый объект Setter задает разные значения свойств для объекта Style. Таким образом, на этом этапе каждая кнопка в приложении имеет ширину величиной 90 и отступ величиной 10. Если нажать клавишу F5 для запуска приложения, отобразится следующее окно.

    Кнопки с шириной 90 и полем 10

    Существует намного больше возможностей по работе со стилями, включая различные способы точной настройки целевых объектов, указание сложных значений свойств и даже использование стилей в качестве входных данных для других стилей. Более подробную информацию см. в разделе Стилизация и использование шаблонов.

  3. Задайте для ресурса значение свойства стиля: ресурсы позволяют простым образом использовать часто определяемые объекты и значения. Особенно эффективным является определение с помощью ресурсов сложных значений для того, чтобы сделать код более модульным. Добавьте следующий выделенный фрагмент с разметкой в файл app.xaml.

    <Application.Resources>
      <LinearGradientBrush x:Key="GrayBlueGradientBrush" StartPoint="0,0" EndPoint="1,1">
        <GradientStop Color="DarkGray" Offset="0" />
        <GradientStop Color="#CCCCFF" Offset="0.5" />
        <GradientStop Color="DarkGray" Offset="1" />
      </LinearGradientBrush>
      <Style TargetType="{x:Type Button}">
        <Setter Property="Background" Value="{StaticResource GrayBlueGradientBrush}" />
        <Setter Property="Width" Value="80" />
        <Setter Property="Margin" Value="10" />
      </Style>
    </Application.Resources>
    

    Непосредственно под блоком Application.Resources вы создали ресурс с именем GrayBlueGradientBrush. Этот ресурс определяет горизонтальный градиент. Этот ресурс можно использовать в качестве значения свойства из любого места в приложении, включая метод задания стиля кнопки для свойства Background. Теперь у всех кнопок имеется значение свойства Background как у этого градиента.

    Нажмите клавишу F5 для запуска приложения. Это должно выглядеть примерно так.

    Кнопки с фоном градиента

Создание шаблона, определяющего внешний вид кнопки

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

До сих пор управление тем, как кнопки выглядят в приложении, ограничивалось изменением свойств кнопки. А что если нужно внести более радикальные изменения во внешний вид кнопки? Шаблоны предоставляют более широкие возможности по управлению внешним видом объекта. Так как шаблоны можно использовать в стилях, шаблоны применимы ко всем объектам, к которым применяется стиль (в этом пошаговом руководстве это кнопка).

Использование шаблона для определения внешнего вида кнопки

  1. Настройте шаблон: вследствие того, что у таких элементов управления, как Button имеется свойство Template, можно определить значение свойства шаблона также, как другие значения свойств, которые задавались ранее в объекте Style с помощью объекта Setter. Добавьте следующий выделенный фрагмент с разметкой в стиль кнопки.

    <Application.Resources>
      <LinearGradientBrush x:Key="GrayBlueGradientBrush"
        StartPoint="0,0" EndPoint="1,1">
        <GradientStop Color="DarkGray" Offset="0" />
        <GradientStop Color="#CCCCFF" Offset="0.5" />
        <GradientStop Color="DarkGray" Offset="1" />
      </LinearGradientBrush>
      <Style TargetType="{x:Type Button}">
        <Setter Property="Background" Value="{StaticResource GrayBlueGradientBrush}" />
        <Setter Property="Width" Value="80" />
        <Setter Property="Margin" Value="10" />
        <Setter Property="Template">
          <Setter.Value>
            <!-- The button template is defined here. -->
          </Setter.Value>
        </Setter>
      </Style>
    </Application.Resources>
    
  2. Измените внешний вид кнопки: на этом этапе нужно определить шаблон. Добавьте следующий выделенный фрагмент с разметкой. В этой разметке задаются два элемента Rectangle с округленными краями, после которых задается объект DockPanel. Объект DockPanel используется для размещения объекта ContentPresenter кнопки. Объект ContentPresenter выполняет отображение содержимого кнопки. В этом пошаговом руководстве содержимое — это текст («Кнопка 1», «Кнопка 2», «Кнопка 3»). Все компоненты шаблона (прямоугольники и объект DockPanel) размещаются внутри объекта Grid.

    <Setter.Value>
      <ControlTemplate TargetType="Button">
        <Grid Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" ClipToBounds="True">
          <!-- Outer Rectangle with rounded corners. -->
          <Rectangle x:Name="outerRectangle" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Stroke="{TemplateBinding Background}" RadiusX="20" RadiusY="20" StrokeThickness="5" Fill="Transparent" />
          <!-- Inner Rectangle with rounded corners. -->
          <Rectangle x:Name="innerRectangle" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Stroke="Transparent" StrokeThickness="20" Fill="{TemplateBinding Background}" RadiusX="20" RadiusY="20" />
          <!-- Present Content (text) of the button. -->
          <DockPanel Name="myContentPresenterDockPanel">
            <ContentPresenter x:Name="myContentPresenter" Margin="20" Content="{TemplateBinding  Content}" TextBlock.Foreground="Black" />
          </DockPanel>
        </Grid>
      </ControlTemplate>
    </Setter.Value>
    

    Нажмите клавишу F5 для запуска приложения. Это должно выглядеть примерно так.

    Окно с 3 кнопками

  3. Добавьте в шаблон эффект стекла: далее нужно добавить эффект стекла. Сначала нужно создать некоторые ресурсы, которые воспроизводят эффект градиента как у стекла. Добавьте эти ресурсы градиента в любое место в блоке Application.Resources:

    <Application.Resources>
      <GradientStopCollection x:Key="MyGlassGradientStopsResource">
        <GradientStop Color="WhiteSmoke" Offset="0.2" />
        <GradientStop Color="Transparent" Offset="0.4" />
        <GradientStop Color="WhiteSmoke" Offset="0.5" />
        <GradientStop Color="Transparent" Offset="0.75" />
        <GradientStop Color="WhiteSmoke" Offset="0.9" />
        <GradientStop Color="Transparent" Offset="1" />
      </GradientStopCollection>
      <LinearGradientBrush x:Key="MyGlassBrushResource"
        StartPoint="0,0" EndPoint="1,1" Opacity="0.75"
        GradientStops="{StaticResource MyGlassGradientStopsResource}" />
    <!-- Styles and other resources below here. -->
    

    Эти ресурсы используются как свойство Fill для прямоугольника, который вставляется в объект Grid из шаблона кнопки. Добавьте в шаблон следующий выделенный фрагмент с разметкой.

    <Setter.Value>
      <ControlTemplate TargetType="{x:Type Button}">
        <Grid Width="{TemplateBinding Width}" Height="{TemplateBinding Height}"
          ClipToBounds="True">
    
        <!-- Outer Rectangle with rounded corners. -->
        <Rectangle x:Name="outerRectangle" HorizontalAlignment="Stretch"
          VerticalAlignment="Stretch" Stroke="{TemplateBinding Background}"
          RadiusX="20" RadiusY="20" StrokeThickness="5" Fill="Transparent" />
    
        <!-- Inner Rectangle with rounded corners. -->
        <Rectangle x:Name="innerRectangle" HorizontalAlignment="Stretch"
          VerticalAlignment="Stretch" Stroke="Transparent" StrokeThickness="20"
          Fill="{TemplateBinding Background}" RadiusX="20" RadiusY="20" />
    
        <!-- Glass Rectangle -->
        <Rectangle x:Name="glassCube" HorizontalAlignment="Stretch"
          VerticalAlignment="Stretch"
          StrokeThickness="2" RadiusX="10" RadiusY="10" Opacity="0"
          Fill="{StaticResource MyGlassBrushResource}"
          RenderTransformOrigin="0.5,0.5">
          <Rectangle.Stroke>
            <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
              <LinearGradientBrush.GradientStops>
                <GradientStop Offset="0.0" Color="LightBlue" />
                <GradientStop Offset="1.0" Color="Gray" />
              </LinearGradientBrush.GradientStops>
            </LinearGradientBrush>
          </Rectangle.Stroke>
          <!-- These transforms have no effect as they are declared here.
          The reason the transforms are included is to be targets
          for animation (see later). -->
          <Rectangle.RenderTransform>
            <TransformGroup>
              <ScaleTransform />
              <RotateTransform />
            </TransformGroup>
          </Rectangle.RenderTransform>
          <!-- A BevelBitmapEffect is applied to give the button a "Beveled" look. -->
          <Rectangle.BitmapEffect>
            <BevelBitmapEffect />
          </Rectangle.BitmapEffect>
        </Rectangle>
    
        <!-- Present Text of the button. -->
        <DockPanel Name="myContentPresenterDockPanel">
          <ContentPresenter x:Name="myContentPresenter" Margin="20"
            Content="{TemplateBinding  Content}" TextBlock.Foreground="Black" />
        </DockPanel>
      </Grid>
    </ControlTemplate>
    </Setter.Value>
    

    Обратите внимание, что свойство Opacity прямоугольника (у которого помимо этого есть свойство x:Name равное «glassCube») имеет значение 0, поэтому при запуске этого примера не отображается «стеклянный» прямоугольник, наложенный сверху. Это сделано для того, чтобы позже добавить в шаблон триггеры для реализации взаимодействия пользователя с кнопкой. Однако можно посмотреть, как выглядит кнопка сейчас, изменив значение Opacity на 1 и запустив приложение. См. следующий рисунок. Прежде чем переходить к следующему шагу, измените значение Opacity обратно на 0.

    Пользовательские кнопки, созданные с помощью XAML

Создание интерактивности для кнопки

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

Простым способом для добавления интерактивности (при наведении указателя мыши, выходе указателя мыши, нажатии кнопки мыши и т. д.) является определение триггеров в шаблоне или стиле. Чтобы создать Trigger, нужно определить условие для свойства, например: значение свойства IsMouseOver у кнопки равняется true. Затем нужно определить методы задания (действия), которые выполняются, когда условие триггера имеет значение «true».

Создание интерактивности для кнопки

  1. Добавьте в шаблон триггеры: добавьте выделенный фрагмент с разметкой в свой шаблон.

    <Setter.Value>
      <ControlTemplate TargetType="{x:Type Button}">
        <Grid Width="{TemplateBinding Width}"
          Height="{TemplateBinding Height}" ClipToBounds="True">
    
          <!-- Outer Rectangle with rounded corners. -->
          <Rectangle x:Name="outerRectangle" HorizontalAlignment="Stretch"
          VerticalAlignment="Stretch" Stroke="{TemplateBinding Background}"
          RadiusX="20" RadiusY="20" StrokeThickness="5" Fill="Transparent" />
    
          <!-- Inner Rectangle with rounded corners. -->
          <Rectangle x:Name="innerRectangle" HorizontalAlignment="Stretch"
            VerticalAlignment="Stretch" Stroke="Transparent"
            StrokeThickness="20"
            Fill="{TemplateBinding Background}" RadiusX="20" RadiusY="20"
          />
    
          <!-- Glass Rectangle -->
          <Rectangle x:Name="glassCube" HorizontalAlignment="Stretch"
            VerticalAlignment="Stretch"
            StrokeThickness="2" RadiusX="10" RadiusY="10" Opacity="0"
            Fill="{StaticResource MyGlassBrushResource}"
            RenderTransformOrigin="0.5,0.5">
            <Rectangle.Stroke>
              <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                <LinearGradientBrush.GradientStops>
                  <GradientStop Offset="0.0" Color="LightBlue" />
                  <GradientStop Offset="1.0" Color="Gray" />
                </LinearGradientBrush.GradientStops>
              </LinearGradientBrush>
            </Rectangle.Stroke>
    
            <!-- These transforms have no effect as they
                 are declared here.
                 The reason the transforms are included is to be targets
                 for animation (see later). -->
            <Rectangle.RenderTransform>
              <TransformGroup>
                <ScaleTransform />
                <RotateTransform />
              </TransformGroup>
            </Rectangle.RenderTransform>
    
              <!-- A BevelBitmapEffect is applied to give the button a
                   "Beveled" look. -->
            <Rectangle.BitmapEffect>
              <BevelBitmapEffect />
            </Rectangle.BitmapEffect>
          </Rectangle>
    
          <!-- Present Text of the button. -->
          <DockPanel Name="myContentPresenterDockPanel">
            <ContentPresenter x:Name="myContentPresenter" Margin="20"
              Content="{TemplateBinding  Content}" TextBlock.Foreground="Black" />
          </DockPanel>
        </Grid>
    
        <ControlTemplate.Triggers>       <!-- Set action triggers for the buttons and define            what the button does in response to those triggers. -->     </ControlTemplate.Triggers>
      </ControlTemplate>
    </Setter.Value>
    
  2. Добавьте триггеры свойств: добавьте выделенный фрагмент с разметкой в блок ControlTemplate.Triggers:

    <ControlTemplate.Triggers>
    
      <!-- Set properties when mouse pointer is over the button. -->   <Trigger Property="IsMouseOver" Value="True">     <!-- Below are three property settings that occur when the           condition is met (user mouses over button).  -->     <!-- Change the color of the outer rectangle when user           mouses over it. -->     <Setter Property ="Rectangle.Stroke" TargetName="outerRectangle"       Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />     <!-- Sets the glass opacity to 1, therefore, the           glass "appears" when user mouses over it. -->     <Setter Property="Rectangle.Opacity" Value="1" TargetName="glassCube" />     <!-- Makes the text slightly blurry as though you           were looking at it through blurry glass. -->     <Setter Property="ContentPresenter.BitmapEffect"        TargetName="myContentPresenter">       <Setter.Value>         <BlurBitmapEffect Radius="1" />       </Setter.Value>     </Setter>   </Trigger>
    
    <ControlTemplate.Triggers/>
    

    Нажмите клавишу F5, чтобы запустить приложение и посмотреть проявление эффекта при наведении указателя мыши на кнопку.

  3. Добавьте триггер фокуса: далее можно добавить аналогичные методы задания для обработки ситуации, когда кнопка получает фокус (например, после ее нажатия пользователем).

    <ControlTemplate.Triggers>
    
      <!-- Set properties when mouse pointer is over the button. -->
      <Trigger Property="IsMouseOver" Value="True">
    
        <!-- Below are three property settings that occur when the
             condition is met (user mouses over button).  -->
        <!-- Change the color of the outer rectangle when user          mouses over it. -->
        <Setter Property ="Rectangle.Stroke" TargetName="outerRectangle"
          Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />
    
        <!-- Sets the glass opacity to 1, therefore, the          glass "appears" when user mouses over it. -->
        <Setter Property="Rectangle.Opacity" Value="1"       TargetName="glassCube" />
    
        <!-- Makes the text slightly blurry as though you were          looking at it through blurry glass. -->
        <Setter Property="ContentPresenter.BitmapEffect"       TargetName="myContentPresenter">
          <Setter.Value>
            <BlurBitmapEffect Radius="1" />
          </Setter.Value>
        </Setter>
      </Trigger>
      <!-- Set properties when button has focus. -->   <Trigger Property="IsFocused" Value="true">     <Setter Property="Rectangle.Opacity" Value="1"       TargetName="glassCube" />     <Setter Property="Rectangle.Stroke" TargetName="outerRectangle"       Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />     <Setter Property="Rectangle.Opacity" Value="1" TargetName="glassCube" />   </Trigger>
    
    </ControlTemplate.Triggers>
    

    Нажмите клавишу F5, чтобы запустить приложение, а затем нажмите одну из кнопок. Обратите внимание, что кнопка остается выделенной после нажатия кнопки, так как на ней по-прежнему сохраняется фокус. Если нажать другую кнопку, то фокус получит эта новая кнопка, а прежняя кнопка его потеряет.

  4. Добавьте анимацию дляMouseEnter триггеров и MouseLeave : далее мы добавим некоторые анимации в триггеры. Добавьте следующую разметку в любое место блока ControlTemplate.Triggers.

    <!-- Animations that start when mouse enters and leaves button. -->
    <EventTrigger RoutedEvent="Mouse.MouseEnter">
      <EventTrigger.Actions>
        <BeginStoryboard Name="mouseEnterBeginStoryboard">
          <Storyboard>
          <!-- This animation makes the glass rectangle shrink in the X direction. -->
            <DoubleAnimation Storyboard.TargetName="glassCube"
              Storyboard.TargetProperty=
              "(Rectangle.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"
              By="-0.1" Duration="0:0:0.5" />
            <!-- This animation makes the glass rectangle shrink in the Y direction. -->
            <DoubleAnimation
            Storyboard.TargetName="glassCube"
              Storyboard.TargetProperty=
              "(Rectangle.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)"
              By="-0.1" Duration="0:0:0.5" />
          </Storyboard>
        </BeginStoryboard>
      </EventTrigger.Actions>
    </EventTrigger>
    <EventTrigger RoutedEvent="Mouse.MouseLeave">
      <EventTrigger.Actions>
        <!-- Stopping the storyboard sets all animated properties back to default. -->
        <StopStoryboard BeginStoryboardName="mouseEnterBeginStoryboard" />
      </EventTrigger.Actions>
    </EventTrigger>
    

    «Стеклянный» прямоугольник сокращается в размере, когда указатель мыши перемещается над кнопкой и возвращается к нормальному размеру при выходе указателя мыши из области кнопки.

    Здесь есть две анимации, которые активируются, когда указатель мыши находится над кнопкой (вызывается событие MouseEnter). В этих анимациях «стеклянный» прямоугольник уменьшается в размерах по осям X и Y. Обратите внимание на свойства у элементов DoubleAnimationDuration и By. Свойство Duration указывает, что анимация выполняется в течение половины секунды, а свойство By указывает, что «стеклянный» слой сжимается на 10 %.

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

  5. Добавьте анимацию при нажатии кнопки: в качестве последнего шага добавим триггер для случая, когда пользователь нажимает кнопку. Добавьте следующую разметку в любое место блока ControlTemplate.Triggers:

    <!-- Animation fires when button is clicked, causing glass to spin.  -->
    <EventTrigger RoutedEvent="Button.Click">
      <EventTrigger.Actions>
        <BeginStoryboard>
          <Storyboard>
            <DoubleAnimation Storyboard.TargetName="glassCube"
              Storyboard.TargetProperty=
              "(Rectangle.RenderTransform).(TransformGroup.Children)[1].(RotateTransform.Angle)"
              By="360" Duration="0:0:0.5" />
          </Storyboard>
        </BeginStoryboard>
      </EventTrigger.Actions>
    </EventTrigger>
    

    Нажмите клавишу F5, чтобы запустить приложение, а затем нажмите одну из кнопок. При нажатии кнопки «стеклянный» прямоугольник вращается.

Итоги

В этом пошаговом руководстве были выполнены следующие практические задания:

  • Создание объекта Style в соответствии с целевым типом объекта (Button).

  • Управление основными свойствами кнопок во всем приложении с помощью объекта Style.

  • Создание таких ресурсов, как градиенты, используемые в соответствии со значениями свойств из методов задания Style.

  • Настройка внешнего вида кнопок во всем приложении путем применения к кнопкам шаблона.

  • Настройка поведения кнопок в ответ на действия пользователя (такие как MouseEnter, MouseLeave и Click) с эффектами анимации.

См. также