共用方式為


如何建立控制項的樣式 (WPF .NET)

使用 Windows Presentation Foundation (WPF),您可以使用自己的可重複使用樣式來自訂現有控制項的外觀。 樣式可以全域套用至您的應用程式、視窗和頁面,或直接套用至控制項。

建立樣式

您可以將 Style 想成是一種可將一組屬性值套用到一或多個元素的便利方式。 您可以在任何衍生自 FrameworkElementFrameworkContentElement 的元素上使用樣式,例如 WindowButton

宣告樣式的最常見方式是在 XAML 檔案的 Resources 區段中宣告成資源。 由於樣式是資源,因此會遵守適用於所有資源的範圍規則。 簡單地說,宣告樣式的位置會影響可套用該樣式的位置。 例如,如果您是在應用程式定義 XAML 檔案的根項目中宣告樣式,就可在應用程式中的任何地方使用該樣式。

<Application x:Class="IntroToStylingAndTemplating.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:IntroToStylingAndTemplating"
             StartupUri="WindowExplicitStyle.xaml">
    <Application.Resources>
        <ResourceDictionary>
            
            <Style x:Key="Header1" TargetType="TextBlock">
                <Setter Property="FontSize" Value="15" />
                <Setter Property="FontWeight" Value="ExtraBold" />
            </Style>
            
        </ResourceDictionary>
    </Application.Resources>
</Application>

如果您在應用程式的其中一個 XAML 檔案中宣告樣式,則該樣式只能在該 XAML 檔案中使用。 如需有關資源範圍規則的詳細資訊,請參閱 XAML 資源概觀

<Window x:Class="IntroToStylingAndTemplating.WindowSingleResource"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:IntroToStylingAndTemplating"
        mc:Ignorable="d"
        Title="WindowSingleResource" Height="450" Width="800">
    <Window.Resources>
        
        <Style x:Key="Header1" TargetType="TextBlock">
            <Setter Property="FontSize" Value="15" />
            <Setter Property="FontWeight" Value="ExtraBold" />
        </Style>
        
    </Window.Resources>
    <Grid />
</Window>

樣式是由 <Setter> 子元素所組成,這些子元素會在套用樣式的元素上設定屬性。 在上述範例中,請注意,樣式會設定為透過 TargetType 屬性套用至 TextBlock 類型。 樣式會將 FontSize 設定為 15,並將 FontWeight 設定為 ExtraBold。 為樣式所變更的每個屬性新增 <Setter>

隱含套用樣式

Style 是將一組屬性值套用到多個元素的便利方式。 例如,請考慮下列 TextBlock 元素及其在視窗中的預設外觀。

<StackPanel>
    <TextBlock>My Pictures</TextBlock>
    <TextBlock>Check out my new pictures!</TextBlock>
</StackPanel>

Styling sample screenshot before

您可以直接在每個 TextBlock 元素上設定 FontSizeFontFamily 等屬性,來變更預設外觀。 不過,如果您想要讓 TextBlock 元素共用某些屬性,您可以在 XAML 檔案的 Resources 區段中建立 Style,如下所示。

<Window.Resources>
    <!--A Style that affects all TextBlocks-->
    <Style TargetType="TextBlock">
        <Setter Property="HorizontalAlignment" Value="Center" />
        <Setter Property="FontFamily" Value="Comic Sans MS"/>
        <Setter Property="FontSize" Value="14"/>
    </Style>
</Window.Resources>

當您將樣式的 TargetType 設定為 TextBlock 類型並省略 x:Key 屬性時,樣式會套用至限定為該樣式的所有 TextBlock 元素,這通常是 XAML 檔案本身。

現在,TextBlock 元素顯示如下。

樣式設定範例螢幕擷取畫面根據樣式

明確套用樣式

如果您將具有值的 x:Key 屬性新增至樣式,則樣式不會再隱含地套用至 TargetType 的所有元素。 只有明確參考樣式的元素才會套用該樣式。

以下是上一節的樣式,但以 x:Key 屬性宣告。

<Window.Resources>
    <Style x:Key="TitleText" TargetType="TextBlock">
        <Setter Property="HorizontalAlignment" Value="Center" />
        <Setter Property="FontFamily" Value="Comic Sans MS"/>
        <Setter Property="FontSize" Value="14"/>
    </Style>
</Window.Resources>

若要套用樣式,請使用 StaticResource 標記延伸,將元素上的 Style 屬性設定為 x:Key 值,如下所示。

<StackPanel>
    <TextBlock Style="{StaticResource TitleText}">My Pictures</TextBlock>
    <TextBlock>Check out my new pictures!</TextBlock>
</StackPanel>

請注意,第一個 TextBlock 元素已套用樣式,而第二個 TextBlock 元素則保持不變。 上一節的隱含樣式已變更為宣告 x:Key 屬性的樣式,這表示受該樣式影響的唯一元素就是直接參考該樣式的元素。

樣式設定範例螢幕擷取畫面 Textblock

樣式一旦套用,不論明確或隱含,都會變成密封且無法變更。 如果您想要變更已套用的樣式,請建立新的樣式來取代現有的樣式。 如需詳細資訊,請參閱 IsSealed 屬性 (Property)。

您可以建立一個物件來根據自訂邏輯選擇要套用的樣式。 如需範例,請參閱為 StyleSelector 類別提供的範例。

以程式設計的方式套用樣式

若要以程式設計的方式將具名的樣式指派給元素,請從資源集合取得該樣式,然後將其指派給元素的 Style 屬性。 資源集合中項目的類型為 Object。 因此,您必須先將擷取的樣式轉換成 System.Windows.Style,再將其指派給 Style 屬性。 例如,下列程式碼會將名為 textblock1TextBlock 樣式設定為已定義的樣式 TitleText

textblock1.Style = (Style)Resources["TitleText"];
textblock1.Style = CType(Resources("TitleText"), Windows.Style)

擴充樣式

也許您要讓兩個 TextBlock 元素共用一些屬性值,例如 FontFamily 和置中 HorizontalAlignment。 但同時也想要文字 [我的圖片] 有一些額外的屬性。 您可以建立一個以第一個樣式為基礎的新樣式來達到該目的,如下所示。

<Window.Resources>
    <!-- .... other resources .... -->

    <!--A Style that affects all TextBlocks-->
    <Style TargetType="TextBlock">
        <Setter Property="HorizontalAlignment" Value="Center" />
        <Setter Property="FontFamily" Value="Comic Sans MS"/>
        <Setter Property="FontSize" Value="14"/>
    </Style>
    
    <!--A Style that extends the previous TextBlock Style with an x:Key of TitleText-->
    <Style BasedOn="{StaticResource {x:Type TextBlock}}"
           TargetType="TextBlock"
           x:Key="TitleText">
        <Setter Property="FontSize" Value="26"/>
        <Setter Property="Foreground">
            <Setter.Value>
                <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                    <LinearGradientBrush.GradientStops>
                        <GradientStop Offset="0.0" Color="#90DDDD" />
                        <GradientStop Offset="1.0" Color="#5BFFFF" />
                    </LinearGradientBrush.GradientStops>
                </LinearGradientBrush>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>

然後,將樣式套 TextBlock用至 。

<StackPanel>
    <TextBlock Style="{StaticResource TitleText}" Name="textblock1">My Pictures</TextBlock>
    <TextBlock>Check out my new pictures!</TextBlock>
</StackPanel>

TextBlock 樣式現在置中,使用 Comic Sans MS 字型,大小為 26,前景色彩設定為範例中顯示的 LinearGradientBrush。 請注意,其會覆寫根據樣式的 FontSize 值。 如果 Style 中有多個 Setter 指向相同屬性,則最後宣告的 Setter 優先。

下列顯示 TextBlock 元素現在看起來的樣子:

已設定樣式的 TextBlocks

TitleText 樣式會擴充已針對 TextBlock 類型所建立的樣式 (透過 BasedOn="{StaticResource {x:Type TextBlock}}" 參考)。 您也可以使用樣式的 x:Key 來擴充具有 x:Key 的樣式。 例如,如果有名為 Header1 的樣式,而您想要擴充該樣式,您可以使用 BasedOn="{StaticResource Header1}"

TargetType 屬性與 x:Key 屬性的關聯性

如先前所示,將 TargetType 屬性設定為 TextBlock 而不指派 x:Key 給樣式,會造成該樣式套用至所有 TextBlock 元素。 在此情況下,x:Key 會隱含地設定為 {x:Type TextBlock}。 這表示如果您明確將 x:Key 值設定為 {x:Type TextBlock} 以外的任何值,則 Style 不會自動套用至所有 TextBlock 元素。 取而代之的是,您必須明確地將樣式 (藉由使用 x:Key 值) 套用到 TextBlock 元素。 如果您的樣式位於資源區段,而且您未在樣式上設定 TargetType 屬性,則必須設定 x:Key 屬性。

除了為 x:Key 提供預設值之外,TargetType 屬性還會指定要套用 setter 屬性的類型。 如果您未指定 TargetType,則必須使用語法 Property="ClassName.Property",以類別名稱限定 Setter 物件中的屬性。 例如,您必須將 Property 設定為 "TextBlock.FontSize""Control.FontSize",而不是設定 Property="FontSize"

另請注意,許多 WPF 控制項都是由其他 WPF 控制項的組合所組成。 如果您建立一個套用到某個型別所有控制項的樣式,可能會獲得非預期的結果。 例如,如果您建立以 WindowTextBlock 類型為目標的樣式,即使 TextBlock 屬於另一個控制項 (例如 ListBox),該樣式也會套用至視窗中的所有 TextBlock 控制項。

另請參閱