Procedura dettagliata: creazione di un pulsante tramite XAML
Questa procedura dettagliata descrive come creare un pulsante animato da usare in un'applicazione Windows Presentation Foundation (WPF). Questa procedura dettagliata usa stili e un modello per creare una risorsa pulsante personalizzata che consente il riutilizzo del codice e della separazione della logica dei pulsanti dalla dichiarazione del pulsante. Questa procedura dettagliata è scritta interamente in XAML (Extensible Application Markup Language).
Importante
Questa procedura dettagliata illustra i passaggi per la creazione dell'applicazione digitando o copiando e incollando Extensible Application Markup Language (XAML) in Visual Studio. Se si preferisce imparare a usare una finestra di progettazione per creare la stessa applicazione, vedere Creare un pulsante usando Microsoft Expression Blend.
La figura seguente mostra i pulsanti completati.
Creare pulsanti di base
Per iniziare, creare un nuovo progetto e aggiungere alcuni pulsanti alla finestra.
Per creare un nuovo progetto WPF e aggiungere pulsanti alla finestra
Avviare Visual Studio.
Crea un nuovo progetto WPF: scegliere Nuovo dal menu File e quindi fare clic su Progetto. Trovare il modello Applicazione Windows (WPF) e denominare il progetto "AnimatedButton". Verrà creata la struttura per l'applicazione.
Aggiungere pulsanti predefiniti di base: tutti i file necessari per questa procedura dettagliata vengono forniti dal modello. Aprire il file Window1.xaml facendo doppio clic su di esso in Esplora soluzioni. Per impostazione predefinita, è presente un Grid elemento in Window1.xaml. Rimuovere l'elemento Grid e aggiungere alcuni pulsanti alla pagina XAML (Extensible Application Markup Language) digitando o copiando e incollando il codice evidenziato seguente 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>
Premere F5 per eseguire l'applicazione; dovrebbe essere visualizzato un set di pulsanti simile alla figura seguente.
Ora che hai creato i pulsanti di base, hai finito di lavorare nel file Window1.xaml. Il resto della procedura dettagliata è incentrato sul file app.xaml, definendo gli stili e un modello per i pulsanti.
Impostare le proprietà di base
Successivamente, impostiamo alcune proprietà su questi pulsanti per controllare l'aspetto e il layout del pulsante. Anziché impostare le proprietà sui pulsanti singolarmente, si useranno le risorse per definire le proprietà dei pulsanti per l'intera applicazione. Le risorse dell'applicazione sono concettualmente simili a fogli di stile CSS (Cascading Style Sheets) esterni per le pagine Web; Tuttavia, le risorse sono molto più potenti rispetto ai fogli di stile CSS (Cascading Style Sheets), come si vedrà alla fine di questa procedura dettagliata. Per altre informazioni sulle risorse, vedi Risorse XAML.
Per utilizzare gli stili per impostare le proprietà di base sui pulsanti
Definire un blocco Application.Resources: aprire app.xaml e aggiungere il markup evidenziato seguente se non è già presente:
<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>
L'ambito della risorsa è determinato dalla posizione in cui si definisce la risorsa. La definizione delle risorse nel
Application.Resources
file app.xaml consente di usare la risorsa da qualsiasi punto dell'applicazione. Per altre informazioni sulla definizione dell'ambito delle risorse, vedi Risorse XAML.Creare uno stile e definire i valori di proprietà di base con esso: aggiungere il markup seguente al
Application.Resources
blocco. Questo markup crea un oggetto Style che si applica a tutti i pulsanti nell'applicazione, impostando i Width pulsanti su 90 e su Margin 10:<Application.Resources> <Style TargetType="Button"> <Setter Property="Width" Value="90" /> <Setter Property="Margin" Value="10" /> </Style> </Application.Resources>
La TargetType proprietà specifica che lo stile si applica a tutti gli oggetti di tipo Button. Ogni Setter oggetto imposta un valore di proprietà diverso per .Style Pertanto, a questo punto ogni pulsante nell'applicazione ha una larghezza di 90 e un margine di 10. Se si preme F5 per eseguire l'applicazione, viene visualizzata la finestra seguente.
C'è molto di più che è possibile fare con gli stili, tra cui un'ampia gamma di modi per ottimizzare gli oggetti di destinazione, specificare valori di proprietà complessi e anche usare gli stili come input per altri stili. Per altre informazioni, vedere Applicazione di stili e modelli.
Impostare un valore della proprietà di stile su una risorsa: le risorse consentono un modo semplice per riutilizzare oggetti e valori comunemente definiti. È particolarmente utile definire valori complessi usando le risorse per rendere il codice più modulare. Aggiungere il markup evidenziato seguente a 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>
Direttamente sotto il
Application.Resources
blocco è stata creata una risorsa denominata "GrayBlueGradientBrush". Questa risorsa definisce una sfumatura orizzontale. Questa risorsa può essere usata come valore della proprietà da qualsiasi punto dell'applicazione, incluso il setter dello stile del pulsante per la Background proprietà. Ora, tutti i pulsanti hanno un Background valore della proprietà di questa sfumatura.Premere F5 per eseguire l'applicazione. Il messaggio sarà simile al seguente.
Creare un modello che definisce l'aspetto del pulsante
In questa sezione viene creato un modello che personalizza l'aspetto (presentazione) del pulsante. La presentazione del pulsante è costituita da diversi oggetti, inclusi rettangoli e altri componenti, per dare un aspetto univoco al pulsante.
Finora, il controllo dell'aspetto dei pulsanti nell'applicazione è stato limitato alla modifica delle proprietà del pulsante. Cosa succede se vuoi apportare modifiche più radicali all'aspetto del pulsante? I modelli consentono un controllo potente sulla presentazione di un oggetto. Poiché i modelli possono essere usati all'interno degli stili, è possibile applicare un modello a tutti gli oggetti a cui si applica lo stile (in questa procedura dettagliata il pulsante).
Per usare il modello per definire l'aspetto del pulsante
Configurare il modello: poiché i controlli come Button hanno una Template proprietà, è possibile definire il valore della proprietà del modello esattamente come gli altri valori delle proprietà impostati in usando Style un Setteroggetto . Aggiungere il markup evidenziato seguente allo stile del pulsante.
<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>
Modifica presentazione del pulsante: a questo punto, è necessario definire il modello. Aggiungere il markup evidenziato seguente. Questo markup specifica due Rectangle elementi con bordi arrotondati, seguiti da un oggetto DockPanel. L'oggetto DockPanel viene utilizzato per ospitare l'oggetto ContentPresenter del pulsante. Un ContentPresenter oggetto visualizza il contenuto del pulsante. In questa procedura dettagliata il contenuto è testo ("Pulsante 1", "Pulsante 2", "Pulsante 3"). Tutti i componenti del modello (i rettangoli e il DockPanel) sono disposti all'interno di un oggetto 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>
Premere F5 per eseguire l'applicazione. Il messaggio sarà simile al seguente.
Aggiungere un effetto vetro al modello: successivamente si aggiungerà il vetro. Prima di tutto si creano alcune risorse che creano un effetto sfumatura di vetro. Aggiungere queste risorse sfumature ovunque all'interno del
Application.Resources
blocco:<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. -->
Queste risorse vengono usate come per Fill un rettangolo inserito nel Grid modello del pulsante. Aggiungere il markup evidenziato seguente al modello.
<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>
Si noti che il Opacity del rettangolo con la
x:Name
proprietà "glassCube" è 0, quindi quando si esegue l'esempio, non viene visualizzato il rettangolo di vetro sovrapposto in alto. Questo avviene perché in seguito verranno aggiunti trigger al modello per quando l'utente interagisce con il pulsante. Tuttavia, è possibile visualizzare l'aspetto del pulsante ora modificando il Opacity valore su 1 ed eseguendo l'applicazione. Vedere la figura seguente. Prima di procedere con il passaggio successivo, tornare Opacity a 0.
Crea interattività pulsante
In questa sezione verranno creati trigger di proprietà e trigger di eventi per modificare i valori delle proprietà ed eseguire animazioni in risposta alle azioni dell'utente, ad esempio spostare il puntatore del mouse sul pulsante e fare clic.
Un modo semplice per aggiungere interattività (mouse-over, mouse-leave, clic e così via) consiste nel definire i trigger all'interno del modello o dello stile. Per creare un Triggeroggetto , definire una proprietà "condition", ad esempio: il valore della proprietà del pulsante IsMouseOver è uguale a true
. Si definiscono quindi setter (azioni) che vengono impostati quando la condizione del trigger è true.
Per creare l'interattività dei pulsanti
Aggiungere trigger di modello: aggiungere il markup evidenziato al modello.
<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>
Aggiungere trigger di proprietà: aggiungere il markup evidenziato al
ControlTemplate.Triggers
blocco:<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/>
Premere F5 per eseguire l'applicazione e visualizzare l'effetto mentre si esegue il puntatore del mouse sui pulsanti.
Aggiungi un trigger di stato attivo: successivamente aggiungeremo alcuni setter simili per gestire il caso quando il pulsante ha lo stato attivo (ad esempio, dopo che l'utente lo fa clic).
<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>
Premere F5 per eseguire l'applicazione e fare clic su uno dei pulsanti. Si noti che il pulsante rimane evidenziato dopo averlo fatto clic perché ha ancora lo stato attivo. Se si fa clic su un altro pulsante, il nuovo pulsante ottiene lo stato attivo mentre l'ultimo lo perde.
Aggiungi animazioni perMouseEnter e MouseLeave : aggiungiamo alcune animazioni ai trigger. Aggiungere il markup seguente in un punto qualsiasi all'interno del
ControlTemplate.Triggers
blocco.<!-- 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>
Il rettangolo di vetro si riduce quando il puntatore del mouse si sposta sul pulsante e torna alle dimensioni normali quando il puntatore esce.
Sono presenti due animazioni attivate quando il puntatore passa sul pulsante (MouseEnter viene generato l'evento ). Queste animazioni riducono il rettangolo di vetro lungo l'asse X e Y. Si notino le proprietà degli DoubleAnimation elementi , Duration e By. Duration Specifica che l'animazione si verifica più di mezzo secondo e By specifica che il vetro si riduce del 10%.
Il secondo trigger di evento (MouseLeave) interrompe semplicemente il primo. Quando si arresta un oggetto Storyboard, tutte le proprietà animate restituiscono i valori predefiniti. Pertanto, quando l'utente sposta il puntatore fuori dal pulsante, il pulsante torna alla modalità di spostamento del puntatore del mouse sul pulsante. Per altre informazioni sulle animazioni, vedere Cenni preliminari sull'animazione.
Aggiungi un'animazione per quando si fa clic sul pulsante: il passaggio finale consiste nell'aggiungere un trigger per quando l'utente fa clic sul pulsante. Aggiungere il markup seguente ovunque all'interno del
ControlTemplate.Triggers
blocco:<!-- 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>
Premere F5 per eseguire l'applicazione e fare clic su uno dei pulsanti. Quando si fa clic su un pulsante, il rettangolo di vetro ruota intorno.
Riepilogo
In questa procedura dettagliata sono stati eseguiti gli esercizi seguenti:
Destinazione di un Style oggetto a un tipo di oggetto (Button).
Proprietà di base controllate dei pulsanti nell'intera applicazione usando .Style
Sono state create risorse come gradienti da usare per i valori delle proprietà dei Style setter.
Personalizzato l'aspetto dei pulsanti nell'intera applicazione applicando un modello ai pulsanti.
Comportamento personalizzato per i pulsanti in risposta alle azioni dell'utente (ad esempio MouseEnter, MouseLeavee Click) che includevano effetti di animazione.
Vedi anche
.NET Desktop feedback