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

Expression Blend Важно
  1. 5 года назад

    Alexandr_Erohin

    Aug 14 Администратор
    Добавлено 5 года назад Alexandr_Erohin

    Данную тему я создал, чтобы наглядно продемонстрировать возможности IDE-среды Expression Blend для создания красивой графики. Для примера стилизуем кнопки, чтобы они имели следующий вид:

    -image-

    СКАЧАТЬ ПРОЕКТ (Expression Blend 4)

    Итак откройте Expression Blend (я использую пока 4-ю версию), создайте новый проект приложения WPF, добавьте на форму 3 кнопки и установите в свойствах каждой кнопки ширину и высоту равную 150 (подробно рассматривать структуру Expression Blend я здесь не буду, на сайте есть множество статей по данной теме, если вы плохо знакомы с данной средой - Expression Blend 4):

    -image-

    Щелкните правой кнопкой мыши по первой кнопке и выберите Edit Template --> Edit Copy чтобы редактировать копию шаблона кнопки. Перейдите в режим конструирования и задайте свойства Content="Orange" и FontSize="15" на панели свойств. (Подробное описание создания шаблонов в Expression Blend).

    -image-

    Рядом с кнопкой конструирования нажмите на кнопку Chrome, чтобы просмотреть структуру шаблона:

    -image-

    Удалите узел Chrome на панели Objects and Timeline. Теперь перетащите из панели Assets элемент Grid в шаблон на панели Objects and Timeline. С помощью графического конструктора нужно создать 3 строки и 3 столбца в Grid используя соотношение 0.1*,0.8*,0.1* для высоты строк и ширины колонок. (Работа с Grid в Expression Blend):

    -image-

    Добавьте внутрь Grid два элемента Ellipse, которые в конечном итоге будут рамкой нашей кнопки. Установите для них свойства на панели Properties:
    StrokeThickness="0", Grid.ColumnSpan="3", Grid.RowSpan="3"
    удалите отступы, а так же добавьте фон (свойство Fill):

    * 1й эллипс

    -image-

    * 2й эллипс

    -image-

    На данном этапе визуальный конструктор должен выглядеть следующим образом:

    -image-

    Теперь добавьте элемент Grid внутрь исходного Grid'a и задайте свойства (панель Properties), строки и столбцы (в визуальном конструкторе или непосредственно в коде), чтобы они соответствовали следующим:

    <Grid Grid.Column="1" Grid.ColumnSpan="1" Grid.Row="1" Grid.RowSpan="1">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="0.033*"></RowDefinition>
                            <RowDefinition Height="0.095*"></RowDefinition>
                            <RowDefinition Height="0.505*"></RowDefinition>
                            <RowDefinition Height="0.246*"></RowDefinition>
                            <RowDefinition Height="0.121*"></RowDefinition>
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="0.114*"/>
                            <ColumnDefinition Width="0.772*"/>
                            <ColumnDefinition Width="0.114*"/>
                        </Grid.ColumnDefinitions>

    Фактически мы помещаем новый контейнер Grid в центр родительского Grid'a. Не забывайте убирать отступы (свойство margin) которые Expression Blend автоматически генерирует при добавлении нового контейнера.

    Добавьте два элемента Ellipse в данный контейнер, один будет отвечать за фон, а второй за блик на кнопке (назовите первый bg_ellipse, а второй highlight_ellipse). Добавьте для них следующие свойства на панели Properties (не забудьте удалить отступы):

    • bg_ellipse --> StrokeThickness="1" VerticalAlignment="Stretch" Grid.ColumnSpan="3" Grid.RowSpan="5"
    • highlight_ellipse --> Stroke="#FF000000" StrokeThickness="0" HorizontalAlignment="Stretch" Margin="0,0,0,0" VerticalAlignment="Stretch" Width="Auto" Height="Auto" Grid.Column="1" Grid.Row="1" Grid.RowSpan="2" Opacity="0.8"

    Добавьте теперь фон для каждого эллипса:

    bg_ellipse

    -image-

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

    highlight_ellipse

    -image-

    Для блика используется обычный полупрозрачный линейный градиент.

    Теперь самое важное, нужно добавить элемент ContentPresenter, который будет содержать контент самой кнопки (если бы мы стилизовали списковый элемент управления, например ListBox, то тогда нужно было бы использовать контейнер ItemsPresenter). Добавьте его между вышеуказанными эллипсами, чтобы контент кнопки (в примере просто текст) помещался поверх фона кнопки, но позади блика. Задайте для ContentPresenter следующие свойства:
    HorizontalAlignment="Center" VerticalAlignment="Center" Grid.ColumnSpan="1" Grid.RowSpan="2" Grid.Row="2" Grid.Column="1"

    Структура шаблона готова! Иерархия элементов в результирующем шаблоне должна выглядеть следующим образом:

    -image-

    Соответственно рабочая область:

    -image-

    Теперь в шаблон нужно добавить триггер, который будет создавать эффект при клике по кнопке. Для этого перейдите на вкладку Triggers и добавьте новый триггер свойства (кнопка +Property). Удалите все триггеры которые Expression Blend добавляет по умолчанию и добавьте триггер реагирующий на изменение свойства IsPressed:

    -image-

    Теперь в режиме включенной анимации измените свойство StrokeThickness на 4 для bg_ellipse, и Margin на 2,2,2,4 для highlight_ellipse. В результате получится несложный эффект увеличения рамки при клике по кнопке.

    Вот и все! Мы создали красивый и относительно простой шаблон для кнопки. По данному примеру можете создать шаблоны для зеленой, красной кнопок, как показано на самом верхнем рисунке. Просто меняйте цвет фона эллипса bg_ellipse (цвет блика можно оставить одинаковым).

    ----------------------------------------------------------------------------------------------------

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

  2. 4 года назад

    Отличная статья, открыла для меня много нового и полезного. Вот только один вопрос, как программно изменить цвет такой кнопки(изменить цвет фона bg_ellipse)? Спасибо.

  3. Alexandr_Erohin

    Feb 28 Администратор
    Добавлено 4 года назад Alexandr_Erohin

    Для этого нужно изменить шаблон, чтобы фон bg_ellipse был привязан к фону кнопки через TemplateBinding. Например для OrangeButton:

    <Style x:Key="OrangeButton" TargetType="{x:Type Button}">
    	<Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}"></Setter>
    	<Setter Property="Background">
    		<Setter.Value>
    			<RadialGradientBrush GradientOrigin="0.5,0.5">
    				<RadialGradientBrush.RelativeTransform>
    					<TransformGroup>
                                                 <ScaleTransform CenterX="0.5" CenterY="0.5" ScaleX="0.865" ScaleY="0.805"></ScaleTransform>
                                                 <SkewTransform AngleX="0" AngleY="0" CenterX="0.5" CenterY="0.5"></SkewTransform>
                                                 <RotateTransform Angle="135.194" CenterX="0.5" CenterY="0.5"></RotateTransform>
                                                 <TranslateTransform X="0.006" Y="0.124"></TranslateTransform>
                                             </TransformGroup>
                                    </RadialGradientBrush.RelativeTransform>
                                    <GradientStop Color="#FFF46B00" Offset="0.809"></GradientStop>
                                    <GradientStop Color="#FFF9FE30" Offset="0"></GradientStop>
                              </RadialGradientBrush>
    		</Setter.Value>
    	</Setter>
    
    ...
    
    <Ellipse x:Name="bg_ellipse" StrokeThickness="1" VerticalAlignment="Stretch" Grid.ColumnSpan="3" Grid.RowSpan="5"
    	  Fill="{TemplateBinding Background}">
    	<Ellipse.Stroke>
    		<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
    			<GradientStop Color="#FF000000" Offset="0"></GradientStop>
    			<GradientStop Color="#FFFFFFFF" Offset="0.472"></GradientStop>
    			<GradientStop Color="#FF000000" Offset="1"></GradientStop>
    		</LinearGradientBrush>
    	</Ellipse.Stroke>
    </Ellipse>
    
    ...

    Этот прием описан здесь - Расширение разметки

или зарегистрируйтесь чтобы ответить