Genomgång: Skapa en knapp med XAML
Syftet med den här genomgången är att lära dig hur du skapar en animerad knapp för användning i ett WPF-program (Windows Presentation Foundation). Den här genomgången använder formatmallar och mallar för att skapa en anpassad knappresurs som tillåter återanvändning av kod och separation av knapplogik från knappdeklarationen. Den här genomgången är helt skriven i XAML (Extensible Application Markup Language).
Viktig
Den här genomgången vägleder dig genom stegen för att skapa programmet genom att skriva eller kopiera och klistra in XAML (Extensible Application Markup Language) i Visual Studio. Om du föredrar att lära dig att använda ett designverktyg för att skapa samma applikation kan du läsa Skapa en knapp med hjälp av Microsoft Expression Blend.
Följande bild visar de färdiga knapparna.
Skapa grundläggande knappar
Vi börjar med att skapa ett nytt projekt och lägga till några knappar i fönstret.
Skapa ett nytt WPF-projekt och lägga till knappar i fönstret
Starta Visual Studio.
Skapa ett nytt WPF-projekt: På menyn Arkiv pekar du på Nyoch klickar sedan på Project. Leta upp mallen Windows-program (WPF) och ge projektet namnet "AnimatedButton". Då skapas skelettet för programmet.
Lägg till grundläggande standardknappar: Alla filer som du behöver för den här genomgången tillhandahålls av mallen. Öppna filen Window1.xaml genom att dubbelklicka på den i Solution Explorer. Som standard finns det ett Grid element i Window1.xaml. Ta bort Grid-elementet och lägg till några knappar på XAML-sidan (Extensible Application Markup Language) genom att skriva eller kopiera och klistra in följande markerade kod i 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>
Tryck på F5 för att köra programmet. du bör se en uppsättning knappar som ser ut som följande bild.
Nu när du har skapat de grundläggande knapparna är du klar med att arbeta i filen Window1.xaml. Resten av genomgången fokuserar på filen app.xaml och definierar format och en mall för knapparna.
Ange grundläggande egenskaper
Nu ska vi ange några egenskaper på de här knapparna för att styra knappens utseende och layout. I stället för att ange egenskaper på knapparna individuellt använder du resurser för att definiera knappegenskaper för hela programmet. Programresurser liknar begreppsmässigt externa sammanhängande formatmallar (CSS) för webbsidor. Resurserna är dock mycket mer kraftfulla än CSS (Cascading Style Sheets), som du ser i slutet av den här genomgången. Mer information om resurser finns i XAML-resurser.
Så här använder du formatmallar för att ange grundläggande egenskaper på knapparna
Definiera ett Application.Resources-block: Öppna app.xaml och lägg till följande markerade markeringar om det inte redan finns där:
<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>
Resursomfånget bestäms av var du definierar resursen. Genom att definiera resurser i
Application.Resources
i filen app.xaml kan resursen användas var som helst i programmet. Mer information om hur du definierar omfånget för dina resurser finns i XAML-resurser.Skapa ett format och definiera grundläggande egenskapsvärden med det: Lägg till följande markering i
Application.Resources
-blocket. Den här markeringen skapar en Style som gäller för alla knappar i programmet och anger Width för knapparna till 90 och Margin till 10:<Application.Resources> <Style TargetType="Button"> <Setter Property="Width" Value="90" /> <Setter Property="Margin" Value="10" /> </Style> </Application.Resources>
Egenskapen TargetType anger att formatet gäller för alla objekt av typen Button. Varje Setter anger ett annat egenskapsvärde för Style. Därför har varje knapp i programmet nu en bredd på 90 och en marginal på 10. Om du trycker på F5 för att köra programmet visas följande fönster.
Det finns mycket mer du kan göra med format, inklusive en mängd olika sätt att finjustera vilka objekt som är mål, ange komplexa egenskapsvärden och till och med använda formatmallar som indata för andra format. För mer information, se Styling och mallhantering.
Ange ett formategenskapsvärde till en resurs: Resurser möjliggör ett enkelt sätt att återanvända vanliga objekt och värden. Det är särskilt användbart att definiera komplexa värden med hjälp av resurser för att göra koden mer modulär. Lägg till följande markerade markup-taggar i 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>
Direkt under
Application.Resources
-blocket skapade du en resurs med namnet "GrayBlueGradientBrush". Den här resursen definierar en vågrät toning. Den här resursen kan användas som ett egenskapsvärde var som helst i programmet, inklusive i knappformatsuppsättningen för egenskapen Background. Nu har alla knappar ett Background egenskapsvärde för den här toningen.Tryck på F5 för att köra programmet. Det bör se ut så här.
Skapa en mall som definierar knappens utseende
I det här avsnittet skapar du en mall som anpassar knappens utseende (presentation). Knapppresentationen består av flera objekt, inklusive rektanglar och andra komponenter för att ge knappen ett unikt utseende.
Hittills har kontrollen över hur knapparna ser ut i programmet begränsats till att ändra knappens egenskaper. Vad händer om du vill göra mer radikala ändringar i knappens utseende? Mallar ger kraftfull kontroll över presentationen av ett objekt. Eftersom mallar kan användas i formatmallar kan du använda en mall för alla objekt som formatet gäller för (i den här genomgången, knappen).
Så här använder du mallen för att definiera knappens utseende
Konfigurera mallen: Eftersom kontroller som Button har en egenskap Template kan du definiera mallegenskapsvärdet precis som de andra egenskapsvärdena som vi har angett i en Style med hjälp av en Setter. Lägg till följande markerade markering i knappformatet.
<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>
Ändra knapppresentation: Nu måste du definiera mallen. Lägg till följande markerade markup. Den här markeringen anger två Rectangle element med rundade kanter följt av en DockPanel. DockPanel används som värd för knappens ContentPresenter. En ContentPresenter visar knappens innehåll. I den här genomgången är innehållet text ("Knapp 1", "Knapp 2", "Knapp 3"). Alla mallkomponenter (rektanglarna och DockPanel) är placerade i en 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>
Tryck på F5 för att köra programmet. Det bör se ut så här.
Lägg till en glasseffect i mallen: Nästa lägger du till glaset. Först skapar du några resurser som skapar en glaseffekt. Lägg till dessa färgövergångsresurser var som helst i
Application.Resources
-blocket.<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. -->
Dessa resurser används som Fill för en rektangel som vi infogar i Grid i knappmallen. Lägg till följande markerade markeringar i mallen.
<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>
Observera att rektangelns Opacity med egenskapen
x:Name
"glassCube" är 0, så när du kör exemplet ser du inte glasrektangeln överlagrad ovanpå. Det beror på att vi senare lägger till utlösare i mallen för när användaren interagerar med knappen. Du kan dock se hur knappen ser ut nu genom att ändra värdet för Opacity till 1 och köra programmet. Se följande bild. Innan du fortsätter till nästa steg ändrar du Opacity tillbaka till 0.
Skapa knappinteraktivitet
I det här avsnittet skapar du egenskapsutlösare och händelseutlösare för att ändra egenskapsvärden och köra animeringar som svar på användaråtgärder som att flytta pekaren över knappen och klicka.
Ett enkelt sätt att lägga till interaktivitet (mus över musen, lämna musen, klicka och så vidare) är att definiera utlösare i mallen eller formatet. Om du vill skapa en Triggerdefinierar du egenskapen "villkor", till exempel: Knappen IsMouseOver egenskapsvärdet är lika med true
. Sedan definierar du setters (åtgärder) som äger rum när utlösarvillkoret är sant.
Skapa knappinteraktivitet
Lägg till mallutlösare: Lägg till den markerade markup-koden i mallen.
<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>
Lägg till egenskapsutlösare: Lägg till den markerade markeringen i
ControlTemplate.Triggers
-blocket:<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/>
Tryck på F5 för att köra programmet och se effekten när du kör muspekaren över knapparna.
Lägg till en fokusutlösare: Nästa lägger vi till några liknande setters för att hantera ärendet när knappen har fokus (till exempel när användaren har klickat på den).
<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>
Tryck på F5 för att köra programmet och klicka på någon av knapparna. Observera att knappen förblir markerad när du har klickat på den eftersom den fortfarande har fokus. Om du klickar på en annan knapp får den nya knappen fokus medan den sista förlorar den.
Lägg till animeringar förMouseEnterochMouseLeave: Nästa lägger vi till några animeringar i utlösarna. Lägg till följande markering någonstans i
ControlTemplate.Triggers
-blocket.<!-- 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>
Glasrektangeln krymper när muspekaren flyttas över knappen och återgår till normal storlek när pekaren lämnar.
Det finns två animeringar som utlöses när pekaren går över knappen (MouseEnter händelsen aktiveras). Dessa animeringar krymper glasrektangeln längs X- och Y-axeln. Observera egenskaperna för de DoubleAnimation elementen – Duration och By. Duration anger att animeringen sker över en halv sekund och By anger att glaset krymper med 10%.
Den andra händelseutlösaren (MouseLeave) stoppar helt enkelt den första. När du stoppar en Storyboardåtergår alla animerade egenskaper till standardvärdena. När användaren flyttar pekaren från knappen återgår därför knappen till det sätt som den var innan muspekaren flyttades över knappen. Mer information om animeringar finns i Översikt över animering.
Lägg till en animering för när knappen klickas: Det sista steget är att lägga till en utlösare för när användaren klickar på knappen. Lägg till följande markering någonstans i
ControlTemplate.Triggers
-blocket:<!-- 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>
Tryck på F5 för att köra programmet och klicka på en av knapparna. När du klickar på en knapp snurrar glasrektangeln runt.
Sammanfattning
I den här genomgången utförde du följande övningar:
Kontrollerade grundläggande egenskaper för knapparna i hela programmet med hjälp av Style.
Skapade resurser såsom gradienter att använda som egenskapsvärden för Style-setters.
Anpassade utseendet på knappar i hela programmet genom att tillämpa en mall på knapparna.
Anpassat beteende för knapparna som svar på användaråtgärder (till exempel MouseEnter, MouseLeaveoch Click) som inkluderade animeringseffekter.
Se även
.NET Desktop feedback