Overzicht: Een knop maken met behulp van XAML
Het doel van dit scenario is om te leren hoe u een knop met animatie maakt voor gebruik in een WPF-toepassing (Windows Presentation Foundation). Deze handleiding gebruikt stijlen en een sjabloon om een aangepaste knopresource te maken, zodat code kan worden hergebruikt en de logica van de knop gescheiden wordt van de knopdeclaratie. Deze walkthrough is volledig geschreven in Extensible Application Markup Language (XAML).
Belangrijk
In dit overzicht wordt u begeleid bij de stappen voor het maken van de toepassing door Extensible Application Markup Language (XAML) te typen of te kopiëren en plakken in Visual Studio. Als u liever wilt weten hoe u een ontwerper gebruikt om dezelfde toepassing te maken, raadpleegt u Een knop maken met behulp van Microsoft Expression Blend.
In de volgende afbeelding ziet u de voltooide knoppen.
Basisknoppen maken
Laten we beginnen met het maken van een nieuw project en het toevoegen van een paar knoppen aan het venster.
Een nieuw WPF-project maken en knoppen toevoegen aan het venster
Start Visual Studio.
Een nieuw WPF-project maken: wijs in het menu BestandNieuwaan en klik vervolgens op Project. Zoek de Windows-toepassing (WPF) sjabloon en geef het project de naam 'AnimatedButton'. Hiermee maakt u het skelet voor de toepassing.
Standaardknoppen toevoegen: Alle bestanden die u nodig hebt voor deze doorloop worden geleverd door de sjabloon. Open het bestand Window1.xaml door erop te dubbelklikken in Solution Explorer. Standaard is er een Grid element in Window1.xaml. Verwijder het element Grid en voeg een paar knoppen toe aan de pagina Extensible Application Markup Language (XAML) door de volgende gemarkeerde code te typen of te kopiëren en plakken in 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>
Druk op F5 om de toepassing uit te voeren; u zou een set knoppen moeten zien die lijken op de volgende afbeelding.
Nu u de basisknoppen hebt gemaakt, bent u klaar met werken in het bestand Window1.xaml. De rest van de handleiding richt zich op het bestand app.xaml, waarin stijlen en een sjabloon voor de knoppen worden gedefinieerd.
Basiseigenschappen instellen
Vervolgens gaan we enkele eigenschappen op deze knoppen instellen om het uiterlijk en de indeling van de knop te bepalen. In plaats van eigenschappen afzonderlijk op de knoppen in te stellen, gebruikt u resources om knopeigenschappen voor de hele toepassing te definiëren. Toepassingsbronnen zijn conceptueel vergelijkbaar met externe Cascading Style Sheets (CSS) voor webpagina's; resources zijn echter veel krachtiger dan Cascading Style Sheets (CSS), zoals u aan het einde van dit scenario zult zien. Zie XAML-resourcesvoor meer informatie over resources.
Stijlen gebruiken om basiseigenschappen op de knoppen in te stellen
Definieer een Application.Resources-blok: Open app.xaml en voeg de volgende gemarkeerde markeringen toe als deze er nog niet is:
<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>
Het resourcebereik wordt bepaald door de locatie waar u de resource definieert. Als u resources definieert in
Application.Resources
in het bestand app.xaml, kan de resource overal in de toepassing worden gebruikt. Zie XAML-resourcesvoor meer informatie over het definiëren van het bereik van uw resources.Een stijl maken en hiermee basiseigenschapswaarden definiëren: voeg de volgende markeringen toe aan het
Application.Resources
blok. Met deze markering wordt een Style gemaakt die van toepassing is op alle knoppen in de toepassing, waarbij de Width van de knoppen wordt ingesteld op 90 en de Margin op 10:<Application.Resources> <Style TargetType="Button"> <Setter Property="Width" Value="90" /> <Setter Property="Margin" Value="10" /> </Style> </Application.Resources>
De eigenschap TargetType geeft aan dat de stijl van toepassing is op alle objecten van het type Button. Elke Setter stelt een andere eigenschapswaarde in voor de Style. Daarom heeft elke knop in de toepassing op dit punt een breedte van 90 en een marge van 10. Als u op F5 drukt om de toepassing uit te voeren, ziet u het volgende venster.
U kunt nog veel meer doen met stijlen, waaronder verschillende manieren om af te stemmen op de objecten waarop objecten zijn gericht, complexe eigenschapswaarden op te geven en zelfs stijlen te gebruiken als invoer voor andere stijlen. Zie Styling and Templatingvoor meer informatie.
Stel een stijl-eigenschapswaarde in naar een resource: Met resources is het eenvoudig veelgebruikte objecten en waarden opnieuw te gebruiken. Het is vooral handig om complexe waarden te definiëren met behulp van resources om uw code modulairer te maken. Voeg de volgende gemarkeerde markeringen toe aan 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>
Direct onder het
Application.Resources
blok hebt u een resource gemaakt met de naam GrayBlueGradientBrush. Deze resource definieert een horizontale kleurovergang. Deze resource kan overal in de toepassing worden gebruikt als eigenschapswaarde, inclusief in de knopstijlsetter voor de eigenschap Background. Nu hebben alle knoppen een Background eigenschapswaarde van deze gradiënt.Druk op F5 om de toepassing uit te voeren. Het moet er als volgt uitzien.
Een sjabloon maken waarmee het uiterlijk van de knop wordt gedefinieerd
In deze sectie maakt u een sjabloon waarmee het uiterlijk (presentatie) van de knop wordt aangepast. De knoppresentatie bestaat uit verschillende objecten, waaronder rechthoeken en andere onderdelen om de knop een uniek uiterlijk te geven.
Tot nu toe is het beheer van de werking van knoppen in de toepassing beperkt tot het wijzigen van de eigenschappen van de knop. Wat als u meer radicale wijzigingen wilt aanbrengen in het uiterlijk van de knop? Sjablonen bieden krachtige controle over de presentatie van een object. Omdat sjablonen in stijlen kunnen worden gebruikt, kunt u een sjabloon toepassen op alle objecten waarop de stijl van toepassing is (in dit overzicht, de knop).
De sjabloon gebruiken om het uiterlijk van de knop te definiëren
De sjabloon instellen: Omdat besturingselementen zoals Button een eigenschap Template hebben, kunt u de waarde van de sjablooneigenschap definiëren, net zoals de andere eigenschapswaarden die we in een Style hebben ingesteld met behulp van een Setter. Voeg de volgende gemarkeerde opmaak toe aan uw knopstijl.
<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>
Knoppresentatie wijzigen: Op dit moment moet u de sjabloon definiëren. Voeg de volgende gemarkeerde markeringen toe. Met deze markering worden twee Rectangle elementen met afgeronde randen opgegeven, gevolgd door een DockPanel. De DockPanel wordt gebruikt om de ContentPresenter van de knop te hosten. Een ContentPresenter geeft de inhoud van de knop weer. In deze handleiding is de inhoud tekst ("Knop 1", "Knop 2", "Knop 3"). Alle sjabloononderdelen (de rechthoeken en de DockPanel) zijn ingedeeld in een 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>
Druk op F5 om de toepassing uit te voeren. Het moet er als volgt uitzien.
Voeg een glaseffect toe aan de sjabloon: Volgende voegt u het glas toe. Eerst maakt u enkele resources om een glazen verloop te creëren. Voeg deze kleurovergangsbronnen overal toe binnen het
Application.Resources
blok:<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. -->
Deze resources worden gebruikt als de Fill voor een rechthoek die we invoegen in de Grid van de knopsjabloon. Voeg de volgende gemarkeerde markeringen toe aan de sjabloon.
<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>
U ziet dat de Opacity van de rechthoek met de eigenschap
x:Name
van 'glassCube' 0 is, dus wanneer u het voorbeeld uitvoert, ziet u de glazen rechthoek niet erbovenop. Dit komt doordat we later triggers toevoegen aan de sjabloon voor wanneer de gebruiker met de knop communiceert. U kunt echter zien hoe de knop er nu uitziet door de Opacity waarde te wijzigen in 1 en de toepassing uit te voeren. Zie de volgende afbeelding. Voordat u doorgaat met de volgende stap, wijzigt u de Opacity terug naar 0.
Maak knop interactiviteit aan
In deze sectie maakt u eigenschaptriggers en gebeurtenistriggers om eigenschapswaarden te wijzigen en animaties uit te voeren als reactie op gebruikersacties, zoals het verplaatsen van de muisaanwijzer over de knop en klikken.
Een eenvoudige manier om interactiviteit (muisaanwijzer, muisverloop, klikken enzovoort) toe te voegen, is door triggers in uw sjabloon of stijl te definiëren. Als u een Triggerwilt maken, definieert u een eigenschap 'voorwaarde', zoals: De knop IsMouseOver eigenschapswaarde is gelijk aan true
. Vervolgens definieert u setters (acties) die plaatsvinden wanneer aan de triggervoorwaarde wordt voldaan.
Knop-interactiviteit maken
Sjabloontriggers toevoegen: Voeg de gemarkeerde markeringen toe aan uw sjabloon.
<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>
Eigenschapstriggers toevoegen: De gemarkeerde markering toevoegen aan het
ControlTemplate.Triggers
-blok:<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/>
Druk op F5 om de toepassing uit te voeren en het effect te zien terwijl u de muis aanwijzer op de knoppen uitvoert.
Een focustrigger toevoegen: Volgende voegen we vergelijkbare setters toe om de case af te handelen wanneer de knop de focus heeft (bijvoorbeeld nadat de gebruiker erop heeft geklikt).
<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>
Druk op F5 om de toepassing uit te voeren en klik op een van de knoppen. U ziet dat de knop gemarkeerd blijft nadat u erop hebt geklikt, omdat deze nog steeds de focus heeft. Als u op een andere knop klikt, krijgt de nieuwe knop de focus terwijl de laatste knop de focus verliest.
Animaties toevoegen voorMouseEnterenMouseLeave: Volgende voegen we enkele animaties toe aan de triggers. Voeg overal in het
ControlTemplate.Triggers
blok de volgende markeringen toe.<!-- 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>
De glazen rechthoek wordt verkleind wanneer de muis aanwijzer over de knop beweegt en teruggaat naar de normale grootte wanneer de aanwijzer vertrekt.
Er zijn twee animaties die worden geactiveerd wanneer de aanwijzer over de knop gaat (MouseEnter event wordt gegenereerd). Deze animaties verkleinen de glazen rechthoek langs de X- en Y-as. Let op de eigenschappen van de DoubleAnimation elementen: Duration en By. De Duration geeft aan dat de animatie over een halve seconde plaatsvindt, en By geeft aan dat het glas met 10%krimpt.
De tweede gebeurtenistrigger (MouseLeave) stopt de eerste. Wanneer u een Storyboardstopt, keren alle geanimeerde eigenschappen terug naar hun standaardwaarden. Wanneer de gebruiker de aanwijzer van de knop verplaatst, gaat de knop daarom terug naar de manier waarop deze zich bevond voordat de muisaanwijzer over de knop is verplaatst. Zie Animatieoverzichtvoor meer informatie over animaties.
Een animatie toevoegen voor wanneer op de knop wordt geklikt: De laatste stap is het toevoegen van een trigger voor wanneer de gebruiker op de knop klikt. Voeg overal in het
ControlTemplate.Triggers
blok de volgende markeringen toe:<!-- 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>
Druk op F5 om de toepassing uit te voeren en klik op een van de knoppen. Wanneer u op een knop klikt, draait de glazen rechthoek rond.
Samenvatting
In deze doorloop hebt u de volgende oefeningen uitgevoerd:
De basiseigenschappen van de knoppen in de hele toepassing zijn geregeld door middel van Style.
Resources gemaakt zoals kleurovergangen die moeten worden gebruikt voor eigenschapswaarden van de Style setters.
Het uiterlijk van knoppen in de hele toepassing aangepast door een sjabloon toe te passen op de knoppen.
Aangepast gedrag voor de knoppen als reactie op gebruikersacties (zoals MouseEnter, MouseLeaveen Click) die animatie-effecten bevatten.
Zie ook
.NET Desktop feedback