Demonstra Passo a passo: Criar um botão usando XAML
The objective of this walkthrough is to learn how to create an animated button for use in a Windows Presentation Foundation (WPF) application. This walkthrough uses styles and a template to create a customized button resource that allows reuse of code and separation of button logic from the button declaration. This walkthrough is written entirely in Extensible Application Markup Language (XAML).
Importante |
---|
This walkthrough guides you through the steps for creating the application by typing or copying and pasting Extensible Application Markup Language (XAML) into Microsoft Visual Studio.If you would prefer to learn how to use a design tool (Microsoft Expression Blend) to create the same application, see Demonstra Passo a passo: Create a Button by Using Microsoft Expression Blend. |
The following figure shows the finished buttons.
Create Basic Buttons
Let's start by creating a new project and adding a few buttons to the window.
To create a new WPF project and add buttons to the window
StartVisual Studio.
Crie um novo projeto do WPF: On the File menu, point to New, and then click Project. Encontrar o Aplicativo WPF (Windows) modelo e o nome do projeto "animatedbutton". This will create the skeleton for the application.
Adicione botões padrão básico: Todos os arquivos que você precisa para esta explicação passo a passo são fornecidos pelo modelo. Open the Window1.xaml file by double clicking it in Solution Explorer. By default, there is a Grid element in Window1.xaml. Remover o Grid elemento e adicionar alguns botões para o Extensible Application Markup Language (XAML) página digitando ou copiar e colar o seguinte código realçado para Window1. XAML:
<Window x:Class="AnimatedButton.Window1" xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="https://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>
Press F5 to run the application; you should see a set of buttons that looks like the following figure.
Now that you have created the basic buttons, you are finished working in the Window1.xaml file. The rest of the walkthrough focuses on the app.xaml file, defining styles and a template for the buttons.
Set Basic Properties
Next, let's set some properties on these buttons to control the button appearance and layout. Rather than setting properties on the buttons individually, you will use resources to define button properties for the entire application. Recursos de aplicativo são conceitualmente semelhantes a externo Cascading Style Sheets (CSS) para páginas da Web; No entanto, os recursos são muito mais poderosos do que Cascading Style Sheets (CSS), como você verá no final desta explicação passo a passo. Para saber mais sobre os recursos, consulte Visão geral sobre Recursos.
To use styles to set basic properties on the buttons
Defina um bloco de Application.Resources: Abra a ser e adicione a seguinte marcação realçada, se ele não já estiver lá:
<Application x:Class="AnimatedButton.App" xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" StartupUri="Window1.xaml" > <Application.Resources> <!-- Resources for the entire application can be defined here. --> </Application.Resources> </Application>
Resource scope is determined by where you define the resource. Defining resources in Application.Resoureses in the app.xaml file enables the resource to be used from anywhere in the application. To learn more about defining the scope of your resources, see Visão geral sobre Recursos.
Crie um estilo e definir valores de propriedade básica com ele: Adicione a seguinte marcação para o Application.Resources bloco. This markup creates a Style that applies to all buttons in the application, setting the Width of the buttons to 90 and the Margin to 10:
<Application.Resources> <Style TargetType="Button"> <Setter Property="Width" Value="90" /> <Setter Property="Margin" Value="10" /> </Style> </Application.Resources>
The TargetType property specifies that the style applies to all objects of type Button. Each Setter sets a different property value for the Style. Portanto, neste momento todos os botões no aplicativo tem uma largura de 90 e uma margem de 10. Se você pressionar F5 para executar o aplicativo, você vê a janela a seguir.
There is much more you can do with styles, including a variety of ways to fine-tune what objects are targeted, specifying complex property values, and even using styles as input for other styles. For more information, see Styling and Templating.
Defina um valor de propriedade de estilo a um recurso: Recursos permitem uma maneira simples de reutilizar comumente definidos objetos e valores. It is especially useful to define complex values using resources to make your code more modular. Add the following highlighted markup to 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>
Directly under the Application.Resources block, you created a resource called "GrayBlueGradientBrush". This resource defines a horizontal gradient. This resource can be used as a property value from anywhere in the application, including inside the button style setter for the Background property. Now, all the buttons have a Background property value of this gradient.
Press F5 to run the application. It should look like the following.
Create a Template That Defines the Look of the Button
In this section, you create a template that customizes the appearance (presentation) of the button. The button presentation is made up of several objects including rectangles and other components to give the button a unique look.
So far, the control of how buttons look in the application has been confined to changing properties of the button. What if you want to make more radical changes to the button's appearance? Templates enable powerful control over the presentation of an object. Because templates can be used within styles, you can apply a template to all objects that the style applies to (in this walkthrough, the button).
To use the template to define the look of the button
Configure o modelo: Porque os controles, como Button tem um Template propriedade, você pode definir o valor da propriedade de modelo assim como os valores de propriedade que definimos em um Style usando um Setter. Add the following highlighted markup to your button style.
<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>
Altere a apresentação do botão: Neste ponto, você precisará definir o modelo. Add the following highlighted markup. This markup specifies two Rectangle elements with rounded edges, followed by a DockPanel. The DockPanel is used to host the ContentPresenter of the button. A ContentPresenter displays the content of the button. In this walkthrough, the content is text ("Button 1", "Button 2", "Button 3"). All of the template components (the rectangles and the DockPanel) are laid out inside of a 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>
Press F5 to run the application. It should look like the following.
Adicione um glasseffect para o modelo: Em seguida, você adicionará o vidro. First you create some resources that create a glass gradient effect. Add these gradient resources anywhere within the Application.Resources block:
<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. -->
These resources are used as the Fill for a rectangle that we insert into the Grid of the button template. Add the following highlighted markup to the template.
<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>
Notice that the Opacity of the rectangle with the x:Name property of "glassCube" is 0, so when you run the sample, you do not see the glass rectangle overlaid on top. This is because we will later add triggers to the template for when the user interacts with the button. However, you can see what the button looks like now by changing the Opacity value to 1 and running the application. See the following figure. Before proceeding to the next step, change the Opacity back to 0.
Create Button Interactivity
In this section, you will create property triggers and event triggers to change property values and run animations in response to user actions such as moving the mouse pointer over the button and clicking.
An easy way to add interactivity (mouse-over, mouse-leave, click, and so on) is to define triggers within your template or style. Para criar um Trigger, você define uma propriedade "condição" como: O botão IsMouseOver o valor da propriedade é igual a true. You then define setters (actions) that take place when the trigger condition is true.
To create button interactivity
Adicione disparadores do modelo: Adicione a marcação realçada no seu modelo.
<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>
Adicione disparadores de propriedade: Adicione a marcação realçada para o ControlTemplate.Triggers bloco:
<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/>
Press F5 to run the application and see the effect as you run the mouse pointer over the buttons.
Adicione um disparador de foco: Em seguida, vamos adicionar alguns setters semelhantes para manipular o caso quando o botão tiver o foco (por exemplo, depois que o usuário clica nele).
<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>
Press F5 to run the application and click on one of the buttons. Notice that the button stays highlighted after you click it because it still has focus. If you click another button, the new button gains focus while the last one loses it.
Adicionar animações para MouseEnter e MouseLeave: Em seguida, adicionamos algumas animações para os disparadores. Add the following markup anywhere inside of the ControlTemplate.Triggers block.
<!-- 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>
The glass rectangle shrinks when the mouse pointer moves over the button and returns back to normal size when the pointer leaves.
There are two animations that are triggered when the pointer goes over the button (MouseEnter event is raised). These animations shrink the glass rectangle along the X and Y axis. Notice the properties on the DoubleAnimation elements — Duration and By. The Duration specifies that the animation occurs over half a second, and By specifies that the glass shrinks by 10%.
The second event trigger (MouseLeave) simply stops the first one. When you stop a Storyboard, all the animated properties return to their default values. Therefore, when the user moves the pointer off the button, the button goes back to the way it was before the mouse pointer moved over the button. For more information about animations, see Revisão de Animação.
Adicione uma animação para quando o botão for clicado: A etapa final é adicionar um disparador para quando o usuário clica no botão. Add the following markup anywhere inside of the ControlTemplate.Triggers block:
<!-- 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>
Press F5 to run the application, and click one of the buttons. When you click a button, the glass rectangle spins around.
Summary
In this walkthrough, you performed the following exercises:
Controlled basic properties of the buttons in the entire application using the Style.
Created resources like gradients to use for property values of the Style setters.
Customized the look of buttons in the entire application by applying a template to the buttons.
Customized behavior for the buttons in response to user actions (such as MouseEnter, MouseLeave, and Click) that included animation effects.
Consulte também
Tarefas
Demonstra Passo a passo: Create a Button by Using Microsoft Expression Blend