다음을 통해 공유


XAML 스타일

XAML 프레임워크를 사용하여 여러 가지 방법으로 앱의 모양을 사용자 지정할 수 있습니다. 스타일을 사용하면 컨트롤 속성을 설정하고 이러한 설정을 여러 컨트롤에서 일관된 모양으로 다시 사용할 수 있습니다.

WinUI 및 스타일

WinUI 2.2부터 WinUI 를 사용하여 UI 구성 요소 간에 새로운 비주얼 스타일 업데이트를 제공했습니다. UI가 최신 스타일로 업데이트되지 않는 경우 최신 WinUI NuGet 패키지로 업데이트해야 합니다.

WinUI 2.6부터 대부분의 컨트롤에 대한 새 스타일과 필요한 경우 이전 컨트롤 스타일로 되돌릴 수 있는 새 버전 관리 시스템을 제공합니다. 새 스타일은 Windows의 디자인 방향과 더 잘 일치하므로 사용하는 것이 좋습니다. 그러나 시나리오에서 새 스타일을 지원할 수 없는 경우 이전 버전을 계속 사용할 수 있습니다.

WinUI 버전 2를 사용할 때, ControlsResourcesVersion에 포함된 XamlControlsResources에 대해 Application.Resources 속성을 설정하여 스타일 버전을 변경할 수 있습니다. ControlsResourcesVersion 기본값은 Version2열거형 값입니다.

이 값을 설정하면 Version1XamlControlsResources 최신 WinUI 버전에서 사용하는 새 스타일 대신 이전 스타일 버전이 로드됩니다. 런타임에 이 속성을 변경하는 것은 지원되지 않으며 VisualStudio의 핫 다시 로드 기능은 작동하지 않습니다. 그러나 애플리케이션을 다시 빌드한 후에는 컨트롤 스타일이 변경되는 것을 볼 수 있습니다.

<Application.Resources>
    <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" 
                           ControlsResourcesVersion="Version1"/>
</Application.Resources>

스타일 기본 사항

스타일을 사용하여 재사용 가능한 리소스로 시각적 속성 설정을 추출합니다. 다음은 BorderBrush, BorderThicknessForeground 속성을 설정하는 스타일이 있는 3개의 단추를 보여 주는 예제입니다. 스타일을 적용하면 각 컨트롤에서 이러한 속성을 별도로 설정하지 않고도 컨트롤이 동일하게 표시되도록 할 수 있습니다.

세 개의 스타일 버튼이 나란히 배열된 스크린샷

컨트롤의 XAML에서 스타일 인라인을 정의하거나 재사용 가능한 리소스로 정의할 수 있습니다. 개별 페이지의 XAML 파일, App.xaml 파일 또는 별도의 리소스 사전 XAML 파일에서 리소스를 정의합니다. 리소스 사전 XAML 파일은 앱 간에 공유할 수 있으며 단일 앱에서 둘 이상의 리소스 사전을 병합할 수 있습니다. 리소스가 정의된 위치에 따라 리소스를 사용할 수 있는 범위가 결정됩니다. 페이지 수준 리소스는 정의된 페이지에서만 사용할 수 있습니다. 동일한 키를 가진 리소스가 App.xaml과 페이지에 모두 정의되어 있을 경우, 페이지의 리소스가 App.xaml의 리소스보다 우선합니다. 리소스가 별도의 리소스 사전 파일에 정의된 경우 해당 범위는 리소스 사전이 참조되는 위치에 따라 결정됩니다.

Style 정의에는 TargetType 특성과 하나 이상의 Setter 요소 컬렉션이 필요합니다. TargetType 특성은 스타일을 적용할 FrameworkElement 형식을 지정하는 문자열입니다. TargetType 값은 Windows 런타임에 의해 정의되었거나 참조된 어셈블리에 있는 사용자 정의 형식에서 제공된 FrameworkElement파생 형식을 지정해야 합니다. 컨트롤에 스타일을 적용하려고 하면 컨트롤의 형식이 적용하려는 스타일의 TargetType 특성과 일치하지 않으면 예외가 발생합니다.

Setter 요소에는 속성이 필요합니다. 이러한 속성 설정은 설정이 적용되는 컨트롤 속성과 해당 속성에 대해 설정할 값을 나타냅니다. 특성 또는 속성 요소 구문을 사용하여 Setter.Value 를 설정할 수 있습니다. 여기서 XAML은 이전에 표시된 단추에 적용된 스타일을 보여 줍니다. 이 XAML에서 처음 두 Setter 요소는 속성 구문을 사용하지만, 마지막 SetterBorderBrush 속성에 대해 속성 요소 구문을 사용합니다. 이 예제에서는 x:Key 특성 특성을 사용하지 않으므로 스타일이 단추에 암시적으로 적용됩니다. 스타일을 암시적으로 또는 명시적으로 적용하는 방법은 다음 섹션에서 설명합니다.

<Page.Resources>
    <Style TargetType="Button">
        <Setter Property="BorderThickness" Value="5" />
        <Setter Property="Foreground" Value="Black" />
        <Setter Property="BorderBrush" >
            <Setter.Value>
                <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                    <GradientStop Color="Yellow" Offset="0.0" />
                    <GradientStop Color="Red" Offset="0.25" />
                    <GradientStop Color="Blue" Offset="0.75" />
                    <GradientStop Color="LimeGreen" Offset="1.0" />
                </LinearGradientBrush>
            </Setter.Value>
        </Setter>
    </Style>
</Page.Resources>

<StackPanel Orientation="Horizontal">
    <Button Content="Button"/>
    <Button Content="Button"/>
    <Button Content="Button"/>
</StackPanel>

암시적 또는 명시적 스타일 적용

스타일을 리소스로 정의하는 경우 컨트롤에 적용하는 두 가지 방법이 있습니다.

스타일에 x:Key 특성이 포함된 경우 컨트롤의 Style 속성을 키 지정 스타일로 설정하여 컨트롤에만 적용할 수 있습니다. 반면 x:Key 특성이 없는 스타일은 대상 형식의 모든 컨트롤에 자동으로 적용되며, 그렇지 않으면 명시적 스타일 설정이 없습니다.

다음은 암시적 스타일과 명시적 스타일을 보여 주는 두 개의 단추입니다.

암시적이고 명시적으로 스타일이 지정된 단추 .

이 예제에서 첫 번째 스타일에는 x:Key 특성 있으며 대상 형식은 Button. 첫 번째 단추의 Style 속성이 이 키로 설정되므로 이 스타일이 명시적으로 적용됩니다. 두 번째 스타일은 대상 유형이 Button 이고 스타일에 x:Key 특성이 없기 때문에 두 번째 단추에 암시적으로 적용됩니다.

<Page.Resources>
    <Style x:Key="PurpleStyle" TargetType="Button">
        <Setter Property="FontFamily" Value="Segoe UI"/>
        <Setter Property="FontSize" Value="14"/>
        <Setter Property="Foreground" Value="Purple"/>
    </Style>

    <Style TargetType="Button">
        <Setter Property="FontFamily" Value="Segoe UI"/>
        <Setter Property="FontSize" Value="14"/>
        <Setter Property="RenderTransform">
            <Setter.Value>
                <RotateTransform Angle="25"/>
            </Setter.Value>
        </Setter>
        <Setter Property="BorderBrush" Value="Green"/>
        <Setter Property="BorderThickness" Value="2"/>
        <Setter Property="Foreground" Value="Green"/>
    </Style>
</Page.Resources>

<Grid x:Name="LayoutRoot">
    <Button Content="Button" Style="{StaticResource PurpleStyle}"/>
    <Button Content="Button"/>
</Grid>

기반 스타일 사용

스타일을 더 쉽게 유지 관리하고 스타일 재사용을 최적화하기 위해 다른 스타일에서 상속되는 스타일을 만들 수 있습니다. BasedOn 속성을 사용하여 상속된 스타일을 만듭니다. 다른 스타일에서 상속되는 스타일은 동일한 형식의 컨트롤 또는 기본 스타일이 대상으로 하는 형식에서 파생되는 컨트롤을 대상으로 해야 합니다. 예를 들어, 기본 스타일이 ContentControl을 대상으로 한다면, 이 스타일을 기반으로 하는 스타일은 ContentControl이나 ContentControl에서 파생되는 형식, 예를 들어 버튼ScrollViewer을 대상으로 지정할 수 있습니다. 기준 스타일에서 값이 설정되지 않은 경우 기본 스타일에서 상속됩니다. 기본 스타일에서 값을 변경하려면 기반 스타일이 해당 값을 재정의합니다. 다음 예제에서는 동일한 기본 스타일을 상속하는 스타일을 사용하는 버튼체크박스를 보여 줍니다.

스타일이 지정된 단추를 스타일에 따라 지정합니다.

기본 스타일은 ContentControl을 대상으로 하여 HeightWidth 속성을 설정합니다. 이 스타일에 기반한 스타일들은 ContentControl에서 파생되어 CheckBox버튼을 대상으로 합니다. 기본 스타일은 BorderBrushForeground 속성에 다양한 색상을 설정합니다. (일반적으로 CheckBox 주위에 테두리를 두지 않습니다. 여기서는 스타일의 효과를 보여 줍니다.)

<Page.Resources>
    <Style x:Key="BasicStyle" TargetType="ContentControl">
        <Setter Property="Width" Value="130" />
        <Setter Property="Height" Value="30" />
    </Style>

    <Style x:Key="ButtonStyle" TargetType="Button"
           BasedOn="{StaticResource BasicStyle}">
        <Setter Property="BorderBrush" Value="Orange" />
        <Setter Property="BorderThickness" Value="2" />
        <Setter Property="Foreground" Value="Red" />
    </Style>

    <Style x:Key="CheckBoxStyle" TargetType="CheckBox"
           BasedOn="{StaticResource BasicStyle}">
        <Setter Property="BorderBrush" Value="Blue" />
        <Setter Property="BorderThickness" Value="2" />
        <Setter Property="Foreground" Value="Green" />
    </Style>
</Page.Resources>

<StackPanel>
    <Button Content="Button" Style="{StaticResource ButtonStyle}" Margin="0,10"/>
    <CheckBox Content="CheckBox" Style="{StaticResource CheckBoxStyle}"/>
</StackPanel>

도구를 사용하여 스타일을 쉽게 작업하십시오.

컨트롤에 스타일을 빠르게 적용하는 방법은 Microsoft Visual Studio XAML 디자인 화면에서 컨트롤을 마우스 오른쪽 버튼으로 클릭하고, 스타일 편집 또는 템플릿 편집을 선택하는 것입니다(클릭한 컨트롤에 따라 다름). 그런 다음 리소스 적용 을 선택하여 기존 스타일을 적용하거나 빈 항목 만들기를 선택하여 새 스타일을 정의할 수 있습니다. 빈 스타일을 만드는 경우 페이지, App.xaml 파일 또는 별도의 리소스 사전에서 정의할 수 있는 옵션이 제공됩니다.

경량 스타일링

시스템 브러시 재정의는 일반적으로 앱 또는 페이지 수준에서 수행되며, 두 경우 모두 색 재정의는 해당 브러시를 참조하는 모든 컨트롤에 영향을 줍니다. XAML에서는 많은 컨트롤이 동일한 시스템 브러시를 참조할 수 있습니다.

두 버튼의 스크린샷입니다: 하나는 기본 상태에 있고, 다른 하나는 경량 스타일이 적용된 상태입니다.

<Page.Resources>
    <ResourceDictionary>
        <ResourceDictionary.ThemeDictionaries>
            <ResourceDictionary x:Key="Light">
                 <SolidColorBrush x:Key="ButtonBackground" Color="Transparent"/>
                 <SolidColorBrush x:Key="ButtonForeground" Color="MediumSlateBlue"/>
                 <SolidColorBrush x:Key="ButtonBorderBrush" Color="MediumSlateBlue"/>
            </ResourceDictionary>
        </ResourceDictionary.ThemeDictionaries>
    </ResourceDictionary>
</Page.Resources>

PointerOver(마우스가 단추 위에 마우스로 가리키기), PointerPressed(단추가 호출됨) 또는 사용 안 함(단추가 상호 작용할 수 없음)과 같은 상태의 경우 원래 경량 스타일 이름에 다음과 같은 엔딩이 추가됩니다: ButtonBackgroundPointerOver, ButtonForegroundPressed, ButtonBorderBrushDisabled등. 이러한 브러시를 함께 수정하면 컨트롤의 색상이 앱의 테마와 일관되게 유지됩니다.

이러한 브러시 재정의를 App.Resources 수준에 배치하면 단일 페이지가 아닌 앱 전체의 모든 버튼이 변경됩니다.

컨트롤별 스타일 지정

다른 경우에는 해당 컨트롤의 다른 버전을 변경하지 않고 특정 방식으로만 한 페이지에서 단일 컨트롤을 변경하는 것이 바람직합니다.

세 개의 스타일 버튼이 순서대로 위아래로 쌓여 있는 스크린샷

<CheckBox Content="Normal CheckBox" Margin="5"/>
<CheckBox Content="Special CheckBox" Margin="5">
    <CheckBox.Resources>
        <ResourceDictionary>
            <ResourceDictionary.ThemeDictionaries>
                <ResourceDictionary x:Key="Light">
                    <SolidColorBrush x:Key="CheckBoxForegroundUnchecked"
                        Color="Purple"/>
                    <SolidColorBrush x:Key="CheckBoxForegroundChecked"
                        Color="Purple"/>
                    <SolidColorBrush x:Key="CheckBoxCheckGlyphForegroundChecked"
                        Color="White"/>
                    <SolidColorBrush x:Key="CheckBoxCheckBackgroundStrokeChecked"  
                        Color="Purple"/>
                    <SolidColorBrush x:Key="CheckBoxCheckBackgroundFillChecked"
                        Color="Purple"/>
                </ResourceDictionary>
            </ResourceDictionary.ThemeDictionaries>
        </ResourceDictionary>
    </CheckBox.Resources>
</CheckBox>
<CheckBox Content="Normal CheckBox" Margin="5"/>

이는 해당 컨트롤이 있는 페이지에 "특수 확인란"이 하나만 적용됩니다.

사용자 지정 컨트롤

기본 제공 컨트롤에 시각적으로 및/또는 기능적으로 정렬될 수 있는 사용자 지정 컨트롤을 빌드하는 경우 암시적 스타일 지정 및 경량 스타일 지정 리소스를 사용하여 사용자 지정 콘텐츠를 정의하는 것이 좋습니다. 리소스를 직접 사용하거나 리소스에 대한 새 별칭을 만들 수 있습니다.

제어 리소스 직접 사용

예를 들어 단추처럼 보이는 컨트롤을 작성하는 경우 다음과 같이 컨트롤이 단추 리소스를 직접 참조하게 할 수 있습니다.

<Style TargetType="local:MyCustomControl">
  <Setter Property="Background" Value="{ThemeResource ButtonBackground}" />
  <Setter Property="BorderBrush" Value="{ThemeResource ButtonBorderBrush}" />
</Style>

컨트롤 리소스를 새 이름으로 별칭 지정

또는 고유한 리소스를 만들려는 경우 해당 사용자 지정 이름을 당사의 기본 경량 스타일 리소스에 별칭을 지정해야 합니다.

예를 들어 사용자 지정 컨트롤의 스타일에는 특별한 리소스 정의가 있을 수 있습니다.

<Style TargetType="local:MyCustomControl">
  <Setter Property="Background" Value="{ThemeResource MyCustomControlBackground}" />
  <Setter Property="BorderBrush" Value="{ThemeResource MyCustomControlBorderBrush}"/>
</Style>

리소스 사전이나 메인 정의에서 경량 스타일 리소스를 사용자 정의 리소스와 연결합니다.

<ResourceDictionary.ThemeDictionaries>
    <ResourceDictionary x:Key="Default">
        <StaticResource x:Key="MyCustomControlBackground" ResourceKey="ButtonBackground" />
        <StaticResource x:Key="MyCustomControlBorderBrush" ResourceKey="ButtonBorderBrush" />
    </ResourceDictionary>        
    <ResourceDictionary x:Key="Light">
        <StaticResource x:Key="MyCustomControlBackground" ResourceKey="ButtonBackground" />
        <StaticResource x:Key="MyCustomControlBorderBrush" ResourceKey="ButtonBorderBrush" />
    </ResourceDictionary>
    <ResourceDictionary x:Key="HighContrast">
        <StaticResource x:Key="MyCustomControlBackground" ResourceKey="ButtonBackground" />
        <StaticResource x:Key="MyCustomControlBorderBrush" ResourceKey="ButtonBorderBrush" />
    </ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>

세 가지 다른 테마 변경 내용을 올바르게 처리하기 위해 세 번 복제된 항목을 사용해야 ThemeDictionary 합니다(Default, Light, HighContrast).

주의

경량 스타일 지정 리소스를 새 별칭에 할당하고 경량 스타일 지정 리소스를 다시 정의하는 경우 리소스 조회가 올바른 순서가 아닌 경우 사용자 지정이 적용되지 않을 수 있습니다. 예를 들어 ButtonBackground 찾기 전에 검색되는 지점에서 MyCustomControlBackground 재정의하는 경우 재정의가 누락됩니다.

컨트롤을 다시 설정하는 것을 방지합니다.

WinUI 2.2 이상에는 WinUI 및 시스템 컨트롤 모두에 대한 새 스타일과 템플릿이 포함되어 있습니다.

최신 비주얼 스타일을 최신 상태로 유지하는 가장 좋은 방법은 최신 WinUI 2 패키지를 사용하고 사용자 지정 스타일 및 템플릿(다시 템플릿이라고도 함)을 방지하는 것입니다. 스타일은 앱의 컨트롤에서 일관되게 값 집합을 적용하는 편리한 방법입니다. 이 작업을 수행할 때는 최신 스타일을 기준으로 삼아야 합니다.

WinUI 스타일(Windows.UI.Xaml.Controls 네임스페이스)을 사용하는 시스템 컨트롤의 경우, BasedOn="{StaticResource Default<ControlName>Style}"가 컨트롤의 이름인 <ControlName>를 설정하세요. 다음은 그 예입니다.

<Style TargetType="TextBox" BasedOn="{StaticResource DefaultTextBoxStyle}">
    <Setter Property="Foreground" Value="Blue"/>
</Style>

WinUI 2 컨트롤(Microsoft.UI.Xaml.Controls 네임스페이스)의 경우, 기본 스타일은 메타데이터에 정의되어 있으므로 BasedOn를 생략하세요.

파생 컨트롤

기존 XAML 컨트롤에서 사용자 지정 컨트롤을 파생하는 경우 기본적으로 WinUI 2 스타일을 가져올 수 없습니다. WinUI 2 스타일을 적용하려면 다음을 수행합니다.

  • TargetType 사용자 지정 컨트롤로 설정된 새 Style 만듭니다.
  • 스타일은 파생된 컨트롤의 기본 스타일을 기반으로 합니다.

이에 대한 일반적인 시나리오 중 하나는 ContentDialog에서 새 컨트롤을 파생하는 것입니다. 이 예제에서는 사용자 지정 대화 상자에 적용되는 새 스타일을 만드는 방법을 보여 줍니다 DefaultContentDialogStyle .

<ContentDialog
    x:Class="ExampleApp.SignInContentDialog"
    ... >

    <ContentDialog.Resources>
        <Style TargetType="local:SignInContentDialog" BasedOn="{StaticResource DefaultContentDialogStyle}"/>
        ...
    </ContentDialog.Resources> 
    <!-- CONTENT -->
</ContentDialog>        

템플릿 속성

스타일 setter는 ControlTemplate 속성에 사용할 수 있습니다. 실제로, 이는 일반적인 XAML 스타일과 앱의 XAML 리소스의 대부분을 구성합니다. 이 내용은 컨트롤 템플릿 항목에서 자세히 설명합니다.