共用方式為


逐步解說:使用 XAML 建立按鈕

本逐步解說的目的是要瞭解如何建立動畫按鈕,以用於 Windows Presentation Foundation (WPF) 應用程式中。 本逐步解說會使用樣式和範本來建立自訂的按鈕資源,以允許重複使用按鈕邏輯的程式碼和分隔按鈕宣告。 本逐步解說完全是以可延伸的應用程式標記語言 (XAML) 撰寫。

重要

本逐步解說會引導您完成建立應用程式的步驟,方法是在 Visual Studio 中輸入或複製並貼上 Extensible Application Markup Language (XAML)。 如果您想要瞭解如何使用設計工具來建立相同的應用程式,請參閱 使用 Microsoft Expression Blend 建立按鈕。

下圖顯示已完成的按鈕。

Custom buttons that were created by using XAML

建立基本按鈕

讓我們從建立新專案並將幾個按鈕新增至視窗開始。

若要建立新的 WPF 專案,並將按鈕新增至視窗

  1. 啟動 Visual Studio。

  2. 建立新的 WPF 專案: 在 [ 檔案 ] 功能表上,指向 [ 新增 ],然後按一下 [ 專案 ]。 尋找 Windows 應用程式 (WPF) 範本,並將專案命名為 「AnimatedButton」。 這會為應用程式建立基本架構。

  3. 新增基本預設按鈕: 範本會提供此逐步解說所需的所有檔案。 在 方案總管中按兩下 Window1.xaml 檔案,以開啟它。 根據預設,Window1.xaml 中有一個專案 GridGrid輸入或複製下列醒目提示的程式碼並貼到 Window1.xaml,以移除 元素,並將幾個按鈕新增至 Extensible Application Markup Language (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>
    

    按 F5 執行應用程式;您應該會看到一組看起來像下圖的按鈕。

    Three basic buttons

    現在您已建立基本按鈕,您已完成在 Window1.xaml 檔案中工作。 本逐步解說的其餘部分著重于 app.xaml 檔案,並定義按鈕的樣式和範本。

設定基本屬性

接下來,讓我們在這些按鈕上設定一些屬性,以控制按鈕外觀和版面配置。 您不會個別設定按鈕上的屬性,而是會使用資源來定義整個應用程式的按鈕屬性。 應用程式資源在概念上與網頁的外部級聯樣式表 (CSS) 類似;不過,資源比級聯樣式表 (CSS) 更強大,如本逐步解說結尾所見。 若要深入瞭解資源,請參閱 XAML 資源

若要使用樣式在按鈕上設定基本屬性

  1. 定義 Application.Resources 區塊: 開啟 app.xaml,並在尚未存在時新增下列醒目提示標記:

    <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>
    

    資源範圍取決於您定義資源的位置。 在 app.xaml 檔案中定義資源 Application.Resources 可讓資源從應用程式中的任何位置使用。 若要深入瞭解如何定義資源範圍,請參閱 XAML 資源

  2. 建立樣式並定義基本屬性值: 將下列標記新增至 Application.Resources 區塊。 此標記會 Style 建立 套用至應用程式中所有按鈕的 ,並將按鈕的 設定為 90,並將 Margin 設定 Width 為 10:

    <Application.Resources>
      <Style TargetType="Button">
        <Setter Property="Width" Value="90" />
        <Setter Property="Margin" Value="10" />
      </Style>
    </Application.Resources>
    

    屬性 TargetType 指定樣式會套用至 類型 Button 的所有物件。 每個 都會 SetterStyle 設定不同的屬性值。 因此,此時應用程式中的每個按鈕的寬度為 90,邊界為 10。 如果您按 F5 來執行應用程式,您會看到下列視窗。

    Buttons with a width of 90 and a margin of 10

    您可以使用樣式執行更多動作,包括各種方式來微調目標物件、指定複雜屬性值,甚至使用樣式做為其他樣式的輸入。 如需詳細資訊,請參閱 設定樣式和範本

  3. 將樣式屬性值設定為資源: 資源可讓您使用簡單的方式來重複使用常用的物件和值。 使用資源定義複雜值,讓您的程式碼更模組化特別有用。 將下列醒目提示的標記新增至 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>
    

    直接在 Application.Resources 區塊底下,您已建立名為 「GrayBlueGradientBrush」 的資源。 此資源會定義水準漸層。 此資源可做為應用程式中任何位置的屬性值,包括 屬性的按鈕樣式 setter Background 內。 現在,所有按鈕都有 Background 這個漸層的屬性值。

    按 F5 執行應用程式。 它應該如下所示。

    Buttons with a gradient background

建立定義按鈕外觀的範本

在本節中,您會建立範本,以自訂按鈕的外觀(簡報)。 按鈕簡報是由數個物件所組成,包括矩形和其他元件,以提供按鈕唯一的外觀。

到目前為止,應用程式中按鈕外觀的控制僅限於變更按鈕的屬性。 如果您想要對按鈕的外觀進行更激進的變更,該怎麼辦? 範本可讓您對物件的呈現進行強大的控制。 因為範本可以在樣式內使用,因此您可以將範本套用至套用樣式的所有物件(在此逐步解說中為按鈕)。

若要使用範本來定義按鈕的外觀

  1. 設定範本: 因為之類的 Button 控制項具有 Template 屬性,因此您可以定義範本屬性值,就像我們在 中使用 中所 Style 設定的其他屬性值一 Setter 樣。 將下列醒目提示標記新增至按鈕樣式。

    <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>
    
  2. 改變按鈕簡報: 此時,您需要定義範本。 新增下列醒目提示標記。 此標記會指定兩 Rectangle 個具有四捨五入邊緣的專案,後面接著 DockPanelDockPanel用來裝載 ContentPresenter 按鈕的 。 顯示 ContentPresenter 按鈕的內容。 在本逐步解說中,內容為文字 (「Button 1」、「Button 2」、「Button 3」 )。 所有範本元件 (矩形和 DockPanel ) 都配置在 內 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>
    

    按 F5 執行應用程式。 它應該如下所示。

    Window with 3 buttons

  3. 將眼鏡新增至範本: 接下來您將新增玻璃。 首先,您會建立一些資源來建立玻璃漸層效果。 在 區塊內的任何位置新增 Application.Resources 這些漸層資源:

    <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. -->
    

    這些資源會當做 Fill 我們插入按鈕範本 之 Grid 矩形的 。 將下列醒目提示標記新增至範本。

    <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>
    

    請注意, Opacity 具有 x:Name 「glassCube」 屬性之矩形的 是 0,因此當您執行範例時,您不會看到上方的玻璃矩形。 這是因為我們稍後會在使用者與按鈕互動時,將觸發程式新增至範本。 不過,您可以將值變更 Opacity 為 1 並執行應用程式,以查看按鈕現在的外觀。 請參閱下圖。 繼續進行下一個步驟之前,請將 Opacity 變更回 0。

    Custom buttons that were created by using XAML

建立按鈕互動

在本節中,您將建立屬性觸發程式和事件觸發程式來變更屬性值並執行動畫,以回應使用者動作,例如將滑鼠指標移至按鈕上並按一下。

新增互動性(滑鼠停留、滑鼠離開、按一下等等)的簡單方法是在範本或樣式中定義觸發程式。 若要建立 Trigger ,您可以定義屬性 「條件」,例如:按鈕 IsMouseOver 屬性值等於 true 。 接著,您可以定義觸發條件為 true 時所發生的 setter(actions)。

若要建立按鈕互動功能

  1. 新增範本觸發程式: 將反白顯示的標記新增至範本。

    <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>
    
  2. 新增屬性觸發程式: 將反白顯示的標記新增至 ControlTemplate.Triggers 區塊:

    <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/>
    

    按 F5 執行應用程式,並在按鈕上執行滑鼠指標時看到效果。

  3. 新增焦點觸發程式: 接下來,我們會新增一些類似的 setter 來處理按鈕有焦點的情況(例如,在使用者按一下它之後)。

    <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>
    

    按 F5 以執行應用程式,然後按一下其中一個按鈕。 請注意,當您按一下按鈕之後,按鈕會保持醒目提示,因為它仍然有焦點。 如果您按一下另一個按鈕,新按鈕會取得焦點,而最後一個按鈕會失去焦點。

  4. 為 和 MouseLeave 新增動畫 MouseEnter 接下來,我們會將一些動畫新增至觸發程式。 在 區塊內的任何位置新增 ControlTemplate.Triggers 下列標記。

    <!-- 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>
    

    當滑鼠指標移至按鈕上方時,玻璃矩形會縮小,當指標離開時會回到正常大小。

    當指標超過按鈕時,會觸發兩個動畫( MouseEnter 引發事件)。 這些動畫會沿著 X 和 Y 軸縮小玻璃矩形。 請注意元素上的 DoubleAnimation 屬性 - DurationByDuration會指定動畫會在半秒以上發生,並 By 指定玻璃壓縮 10%。

    第二個事件觸發程式 ( MouseLeave ) 只會停止第一個事件。 當您停止 Storyboard 時,所有動畫屬性都會傳回其預設值。 因此,當使用者將指標移離按鈕時,按鈕會回到滑鼠指標移至按鈕上方之前的方式。 如需動畫的詳細資訊,請參閱 動畫概觀

  5. 在按一下按鈕時新增的動畫: 最後一個步驟是在使用者按一下按鈕時新增 的觸發程式。 在 區塊內的任何位置新增 ControlTemplate.Triggers 下列標記:

    <!-- 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>
    

    按 F5 以執行應用程式,然後按一下其中一個按鈕。 當您按一下按鈕時,玻璃矩形會四處旋轉。

摘要

在本逐步解說中,您執行了下列練習:

  • Style 物件類型 ( Button ) 為目標的 。

  • 使用 Style 控制整個應用程式中按鈕的基本屬性。

  • 已建立像是漸層的資源,以用於 setter 的 Style 屬性值。

  • 將範本套用至按鈕,以自訂整個應用程式中的按鈕外觀。

  • 按鈕的自訂行為,以回應包含動畫效果的使用者動作(例如 MouseEnterMouseLeaveClick )。

另請參閱