프로그램 개발/WPF: Style&Template

NavigationWindow①

(ㅇㅅㅎ) 2022. 6. 11. 17:01
728x90
반응형

 

 안녕하세요, 이번 글에서는 Microsoft에서 제공하는 WPF [NavigationWindow의 스타일 및 템플릿] 예제를 톺아보겠습니다. NavigationWindow Style의 경우 NavWinButtonStyle, NavWinMenu, NavWinHeaderMenuItem, NavWinSubmenuItem, NavigationWindow, ResizeGrip 순서로 나눠져 있습니다. 이번 글에서는 NavigationWindow에 대해서 보도록 하겠습니다.

 

 

 

NavigationWindow

 Content 탐색을 지원하는 창을 나타냅니다.

 

 

 

NavigationWindow Style

 예제의 XAML 코드를 NavigationWindow에 적용하면 위와 같은 결과가 나옵니다. 이러한 결과에 도달하도록 코드 순서로 속성을 살펴보면 다음과 같습니다.

 

 

 

NavigationWindow 속성

<Style x:Key="{x:Type NavigationWindow}" TargetType="{x:Type NavigationWindow}">
  <Setter Property="SnapsToDevicePixels" Value="true" />
  <Setter Property="Template">
    <Setter.Value>
      ...
    </Setter.Value>
  </Setter>
</Style>

x:Key

 XAML 정의 사전에서 만들고 참고하는 요소를 고유하게 식별합니다. 문자를 이용하여 값을 설정하지만 예제에서처럼 x:Type을 사용하여 Control 자체에 바로 적용하도록 설정할 수 있습니다.

 

 

TargetType

 이 Style을 적용할 형식을 설정합니다.

 

 

SnapsToDevicePixels

 렌더링 하는 동안 NavigationWindow의 렌더링에 디바이스 관련 픽셀 스냅(Pixel Snap)을 사용할지 여부를 설정합니다. 픽셀 스냅을 사용하면 값을 true로 설정하고, 그렇지 않으면 false로 설정합니다.

⭐ 픽셀 스냅(Pixel Snap)을 사용하는 이유

더보기

 WPF는 시스템 DPI 설정에 맞게 자동으로 크기를 조정하게 됩니다. 조정할 때 가장자리가 흐려지거나 반투명하게 표시되는 문제가 발생하는데, 이 문제를 해결하기 위해서 픽셀 스냅 기능을 사용하여 객체의 가장자리를 픽셀에 맞추어 고정시키는 기능을 제공합니다. 픽셀 스냅을 사용하면 객체에 작은 단위의 offset을 적용하여 객체의 크기를 픽셀에 맞추거나 일부분을 렌더링 시점에서 제거하여 해결하는 방법입니다.


 

 

Template

<Setter Property="Template">
  <Setter.Value>
    <ControlTemplate TargetType="{x:Type NavigationWindow}">
      <DockPanel>
        ...
        <Border ... >
          ...
          <Grid>
            ...
            <Menu x:Name="NavMenu" ... >
              <MenuItem ... >
                ...
              </MenuItem>
            </Menu>
            <Path ... >
              ... 
            </Path>
            <Button ...  />
            <Button ... />
          </Grid>
        </Border>
        <Grid>
          <AdornerDecorator>
            <Border ... >
              ...
              <ContentPresenter x:Name="PART_NavWinCP" ... />
            </Border>
          </AdornerDecorator>
          <ResizeGrip x:Name="WindowResizeGrip" ... />
        </Grid>
      </DockPanel>
      
      <ControlTemplate.Triggers>
        ...
      </ControlTemplate.Triggers>
    </ControlTemplate>
  </Setter.Value>
</Setter>

 Control의 템플릿을 설정합니다. 예제에서 사용되는 Template는 Control의 외형을 지정해줄 수 있는 ControlTemplate입니다.

👀 Template에 대해서 좀 더 아시고 싶으신 분은 이 페이지를 참고하시길 바랍니다.

 

 

 

NavigationWindow 구성

 

 NavigationWindow은 DockPanel에서  Border와 Grid로 나누어집니다. Border는 NavigationWindow에서 윗부분에 위치하며 주로 NavigationWindow의 Source 이동에 관한 Control이 구성되어있습니다. Grid는 내부에 NavigationWindow의 Source인 ContentPresenter와 창 사이즈를 조정할 수 있는 ResizeGrip이 구성되어있습니다.

 

DockPanel

 자식 요소를 서로 맞춰 가로 또는 세로로 정렬할 수 있는 영역을 정의합니다.

⭐ DocPanel에서 알아두면 좋은 간단한 정보

더보기

 Doc은 자식 Control에서 DocPanel.Doc을 사용하여 설정합니다. 값으로는 Left, Top, Right, Bottom이 있습니다. Control의 순서에 따라서 구성 유형이 달라질 수 있습니다.

 기본 설정인 DockPanel.LastCHildFill 속성을 true(기본값)로 설정하는 경우 DockPanel의 마지막 자식 요소는 마지막 자식 요소에 설정한 다른 dock 값에 관계없이 항상 나머지 공간을 채웁니다.


⭐ DockPanel 속성

더보기
<DockPanel>
  <DockPanel.Background>
    <SolidColorBrush Color="{DynamicResource WindowColor}" />
  </DockPanel.Background>
  ...
</DockPanel>

 

Background

 DockPanel의 배경색을 설정합니다. 예제에서는 SolidColorBrush를 사용하여 WindowColor로 설정했습니다.


 

Border

 다른 요소의 주위에 윤곽선, 배경 또는 둘 다를 그립니다.

⭐ Border 속성

더보기

[ 위쪽 ]

<Border DockPanel.Dock="Top" Height="30" BorderThickness="1">
  <Border.BorderBrush>
    <SolidColorBrush Color="{DynamicResource BorderMediumColor}" />
  </Border.BorderBrush>
  ...
</Border>

[ 아래쪽 ]

<Border BorderThickness="1">
  <Border.BorderBrush>
    <SolidColorBrush Color="{DynamicResource BorderMediumColor}" />
  </Border.BorderBrush>
  ... 
</Border>

 

DockPanel.Dock

 Doc 내에 있는 자식 요소의 DockPanel 위치를 지정합니다. 값으로는 Left, Top, Right, Bottom이 있습니다. 

 

Height

 Border의 높이를 설정합니다. 

 

BorderThickness

 Border의 윤곽선 두께를 설정합니다. 

 

BorderBrush

 Border의 윤곽선 색을 설정합니다. 예제에서는 위쪽과 아래쪽 모두 SolidColorBrush를 사용하여 BorderMediumColor로 설정했습니다.


 

Grid

 열 및 행으로 구성되는 유연한 모눈 영역을 정의합니다.

⭐ Grid 속성

더보기

[ 위쪽 ]

<Grid>
  <Grid.Background>
    <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
      <LinearGradientBrush.GradientStops>
        <GradientStopCollection>
          <GradientStop Color="{DynamicResource ControlLightColor}" Offset="0.0" />
          <GradientStop Color="{DynamicResource ControlMediumColor}" Offset="1.0" />
        </GradientStopCollection>
      </LinearGradientBrush.GradientStops>
    </LinearGradientBrush>
  </Grid.Background>
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="Auto" />
    <ColumnDefinition Width="Auto" />
    <ColumnDefinition Width="16" />
    <ColumnDefinition Width="*" />
  </Grid.ColumnDefinitions>
  ...
</Grid>

 아래쪽은 속성이 따로 없습니다.

Background

 Grid의 배경색을 설정합니다. 예제에서는 LinearGradientBrush를 사용하여 그라데이션 색으로 설정했습니다.

👀 그라데이션 색에 대해서 알고 싶으신 분은 이 페이지를 참고하시길 바랍니다.

 

ColumnDefinitions

 Grid에 ColumnDefinition을 사용하여 ColumnDefinitionCollection(ColumnDefinition 개체의 순서가 지정된 컬렉션)을 설정합니다.

 

ColumnDefinition

 Grid 요소에 적용되는 열 별 속성을 정의합니다. Width로 너비를 숫자 값, 'Auto' 또는 '*'로 설정할 수 있습니다.


 

Menu(NavMenu)

 명령 및 이벤트 처리기에 연결된 요소를 계층적으로 구성할 수 있는 Windows 메뉴 Control을 나타냅니다.

Menu 속성

더보기
<Menu x:Name="NavMenu" Grid.ColumnSpan="3" Height="20" Margin="1,0,0,0" VerticalAlignment="Center" Style="{StaticResource NavWinMenu}">
  ...
</Menu>

 

x:Name

 Menu에 이름을 설정합니다. 이름을 설정하는 것과 동시에 다른 곳에서 사용할 수 있도록 만들어줍니다.

 

Grid.ColumnSpan

 Grid에서 Menu를 채울 전체 열 수를 설정합니다.

 

Height

 Menu의 높이를 설정합니다.

 

Margin

 Menu의 외부 여백을 설정합니다. 예제에서는 값을 4개(좌, 상, 우, 하)로 나누어서 설정했습니다.

 

VerticalAlignment

 Menu의 세로 맞춤 설정입니다. 기본값은 Stretch이며, 다른 값으로는 Left, Center, Right가 있습니다.

 

Style

 Style은 Menu에 속성, 리소스 및 이벤트 처리기를 공유할 수 있게 합니다. 이러한 Style을 미리 정의한 후 Key 값을 이용하여 Menu에 설정합니다. 예제에서는 미리 정의한 NavWinMenu로 설정했습니다.


 

MenuItem

 Menu 내의 선택 가능한 항목을 나타냅니다.

MenuItem 속성

더보기
<MenuItem Style="{StaticResource NavWinHeaderMenuItem}" ItemContainerStyle="{StaticResource NavWinSubmenuItem}" IsSubmenuOpen="{Binding (MenuItem.IsSubmenuOpen), Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}">
  <MenuItem.ItemsSource>
    <MultiBinding Converter="{StaticResource JournalEntryUnifiedViewConverter}">
      <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="BackStack" />
      <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="ForwardStack" />
    </MultiBinding>
  </MenuItem.ItemsSource>
</MenuItem>

 

Style

 Style은 MenuItem에 속성, 리소스 및 이벤트 처리기를 공유할 수 있게 합니다. 이러한 Style을 미리 정의한 후 Key 값을 이용하여 MenuItem에 설정합니다. 예제에서는 미리 정의한 NavWinHeaderMenuItem로 설정했습니다.

 

ItemContainerStyle

 각 항목에 대해 생성된 Container 요소에 적용된 Style을 설정합니다. 예제에서는 미리 정의한 NavWinSubmenuItem으로 설정했습니다.

 

IsSubmenuOpen

 MenuItem의 하위 메뉴가 열려 있는지 여부를 설정합니다. 예제에서는 Binding을 사용하여 부모 MenuItem의 IsSubmeuOpen로 설정했습니다.

 

ItemsSource

 ItemsControl의 Content를 생성하는 데 사용되는 컬렉션을 설정합니다. 예제에서는 MultiBinding을 사용하여 부모의 BackStack과 ForwardStack의 값을 JournalEntryUnifiedViewConverter로 변형한 값을 설정했습니다.


 

Path

 일련의 연결된 선 및 곡선을 그립니다.

⭐ Path 속성

더보기
<Path Grid.Column="0" SnapsToDevicePixels="false" IsHitTestVisible="false" Margin="2,1.5,0,1.5" Grid.ColumnSpan="3" StrokeThickness="1" HorizontalAlignment="Left" VerticalAlignment="Center"
      Data="M22.5767,21.035 Q27,19.37 
            31.424,21.035 A12.5,12.5,0,0,0,53.5,13
            A12.5,12.5,0,0,0,37.765,0.926
            Q27,4.93 16.235,0.926
            A12.5,12.5,0,0,0,0.5,13 
            A12.5,12.5,0,0,0,22.5767,21.035 z">
  <Path.Stroke>
    <SolidColorBrush Color="{DynamicResource BorderMediumColor}" />
  </Path.Stroke>
  <Path.Fill>
    <LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
      <GradientStop Color="{DynamicResource ControlMediumColor}" Offset="0" />
      <GradientStop Color="{DynamicResource ControlDarkColor}" Offset="0.984" />
    </LinearGradientBrush>
  </Path.Fill>
</Path>

 

Grid.Column

 표시할 Grid의 열 자식 Content를 나타내는 값을 설정합니다.

 

SnapsToDevicePixels

 렌더링 하는 동안 Path의 렌더링에 디바이스 관련 픽셀 스냅(Pixel Snap)을 사용할지 여부를 설정합니다. 픽셀 스냅을 사용하면 값을 true로 설정하고, 그렇지 않으면 false로 설정합니다.

 

IsHitTestVisible

 렌더링 된 Content의 일부에서 롤오버 테스트 결과로 반환될 수 있는지 여부를 선언하는 값을 설정합니다.

 

Margin

 Path의 외부 여백을 설정합니다. 예제에서는 4개(좌, 상, 우, 하)로 나누어서 설정했습니다. 

 

Grid.ColumnSpan

 Grid에서 Path를 채울 전체 열 수를 설정합니다.

 

StrokeThickness

 도형 윤곽선의 두께를 설정합니다.

 

HorizontalAlignment

 Path의 가로 맞춤 설정입니다. 기본값은 Stretch이며, 다른 값으로는 Left, Center, Right가 있습니다.

 

VerticalAlignment

 Path의 세로 맞춤 설정입니다. 기본값은 Stretch이며, 다른 값으로는 Top, Center, Bottom이 있습니다.

 

Data

 그릴 모양을 지정하는 Geometry를 설정합니다.

👀 Data 값에 대한 자세한 설명은 이 페이지를 참고하시길 바랍니다.

 

Stroke

 도형 윤곽선 색을 설정합니다. 예제에서는 SolidColorBrush를 사용하여 BorderMediumColor로 설정했습니다.

 

Fill

 도형의 내부 색을 설정합니다. 예제에서는 LinearGradientBrush를 사용하여 그라데이션 색으로 설정했습니다.

👀 그라데이션 색에 대해서 알고 싶으신 분은 이 페이지를 참고하시길 바랍니다.


 

Button

 Click 이벤트에 반응하는 Windows Control을 나타냅니다.

⭐ Button 속성

더보기
<Button Style="{StaticResource NavWinButtonStyle}" Command="NavigationCommands.BrowseBack" Content="M 4 0 L 0 4 L 4 8 Z" Margin="3,1.5,2,1.5" Grid.Column="0" />
<Button Style="{StaticResource NavWinButtonStyle}" Command="NavigationCommands.BrowseForward" Content="M 4 0 L 0 4 L 4 8 Z" Margin="2,1.5,0,1.5" Grid.Column="1" />

 

Style

 Style은 Button에 속성, 리소스 및 이벤트 처리기를 공유할 수 있게 합니다. 이러한 Style을 미리 정의한 후 Key 값을 이용하여 Button에 설정합니다. 예제에서는 미리 정의한 NavWinButtonStyle로 설정했습니다.

 

Command

 Button을 누를 때 호출할 명령을 설정합니다. 예제에서는 NavigationWindow의 이전과 다음으로 이동하는 값으로 설정했습니다.

🌟 NavigationCommands.BrowseBack : Browse Back 명령을 나타내는 값

🌟 NavigationCommands.BrowseForward : Browse Forward 명령을 나타내는 값

 

Content

 ContentControl의 내용을 설정합니다. 예제에서는 ◀와 ▶로 설정했습니다.

 

Margin

 Button의 외부 여백을 설정합니다. 예제에서는 4개(좌, 상, 우, 하)로 나누어서 설정했습니다.

 

Grid.Column

 표시할 Grid의 열 자식 Content를 설정합니다.


 

AdornerDecorator

 시각적 트리의 자식 요소에 대한 AdornerLayer를 제공합니다.

 

ContentPresenter(PART_NavWinCp)

 ContentControl의 내용을 표시합니다. 예제에서는 NavigationWindow의 페이지를 표현합니다.

⭐ ContentPresenter 속성

더보기
<ContentPresenter x:Name="PART_NavWinCP" ClipToBounds="true" />

 

x:Name

 ContentPresenter에 이름을 설정합니다. 이름을 설정하는 것과 동시에 다른 곳에서 사용할 수 있도록 만들어줍니다.

 

ClipToBounds

 요소를 포함하는 Container의 크기에 맞게 이 요소의 Content 또는 이 요소의 자식 요소의 Content를 잘라 낼지 여부를 설정합니다. Content를 잘라야 하면 true이고, 그렇지 않으면 false입니다.


 

ResizeGrip

 Thumb의 크기를 변경할 수 있도록 지원하는 Window Control을 나타냅니다.

ResizeGrip 속성

더보기
<ResizeGrip x:Name="WindowResizeGrip" HorizontalAlignment="Right" VerticalAlignment="Bottom" Visibility="Collapsed" IsTabStop="false" />

 

x:Name

 ResizeGrip에 이름을 설정합니다. 이름을 설정하는 것과 동시에 다른 곳에서 사용할 수 있도록 만들어줍니다.

 

HorizontalAlignment

 ResizeGrip의 가로 정렬 위치를 설정합니다. 기본값은 Stretch이며, 다른 값으로는 Left, Center, Right가 있습니다.

 

VerticalAlignment

 ResizeGrip의 세로 정렬 위치를 설정합니다. 기본값은 Stretch이며, 다른 값으로는 Top, Center, Bottom이 있습니다.

 

Visibility

 ResizeGrip의 표시 유형을 설정합니다. 기본 값은 Visible이며, 다른 값으로는 Collapsed와 Hidden이 있습니다.

 

IsTabStop

 ResizeGrip이 탭 탐색에 포함되는지 여부를 설정합니다. 탭 탐색에 포함되면 true이고, 그렇지 않으면 false입니다.


 

 

NavigationWindow 이벤트

 예제에서는 ResizeMode 이벤트를 Trigger로 표현하였습니다.

 

Triggers

<ControlTemplate.Triggers>
  <Trigger Property="ResizeMode" Value="CanResizeWithGrip">
    <Setter TargetName="WindowResizeGrip" Property="Visibility" Value="Visible" />
  </Trigger>
</ControlTemplate.Triggers>

 Trigger는 어떤 조건이나 이벤트 등이 주어졌을 때 Control의 상태 또는 이벤트 핸들러 등을 호출하는 기능을 의미합니다. 예제에서는 ResizeMode의 값이 CanResizeWithGrip일 경우 WindowResizeGrip의 Visibility를 Visible로 변경하는 것입니다.

 

 

 


 

 

 

전체 코드

더보기
<Style x:Key="NavWinButtonStyle"
       TargetType="{x:Type Button}">
  <Setter Property="OverridesDefaultStyle"
          Value="true" />
  <Setter Property="Command"
          Value="NavigationCommands.BrowseBack" />
  <Setter Property="Focusable"
          Value="false" />
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type Button}">
        <Grid>
          <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="CommonStates">
              <VisualState x:Name="Normal" />
              <VisualState x:Name="MouseOver">
                <Storyboard>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="Ellipse"
                                                Storyboard.TargetProperty="(Shape.Fill).
                    (GradientBrush.GradientStops)[1].(GradientStop.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource ControlMouseOverColor}" />
                  </ColorAnimationUsingKeyFrames>
                </Storyboard>
              </VisualState>
              <VisualState x:Name="Pressed">
                <Storyboard>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="Ellipse"
                                                Storyboard.TargetProperty="(Shape.Fill).
                    (GradientBrush.GradientStops)[1].(GradientStop.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource ControlPressedColor}" />
                  </ColorAnimationUsingKeyFrames>
                </Storyboard>
              </VisualState>
              <VisualState x:Name="Disabled">
                <Storyboard>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="Ellipse"
                                                Storyboard.TargetProperty="(Shape.Fill).
                    (GradientBrush.GradientStops)[1].(GradientStop.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource DisabledControlDarkColor}" />
                  </ColorAnimationUsingKeyFrames>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="Arrow"
                                                Storyboard.TargetProperty="(Shape.Fill).
                    (SolidColorBrush.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource DisabledForegroundColor}" />
                  </ColorAnimationUsingKeyFrames>
                </Storyboard>

              </VisualState>
            </VisualStateGroup>
          </VisualStateManager.VisualStateGroups>
          <Ellipse x:Name="Ellipse"
                   StrokeThickness="1"
                   Width="24"
                   Height="24">
            <Ellipse.Stroke>
              <SolidColorBrush Color="{DynamicResource NavButtonFrameColor}" />
            </Ellipse.Stroke>
            <Ellipse.Fill>
              <LinearGradientBrush StartPoint="0,0"
                                   EndPoint="0,1">
                <LinearGradientBrush.GradientStops>
                  <GradientStopCollection>
                    <GradientStop Color="{DynamicResource ControlLightColor}" />
                    <GradientStop Color="{DynamicResource ControlMediumColor}"
                                  Offset="1.0" />
                  </GradientStopCollection>
                </LinearGradientBrush.GradientStops>
              </LinearGradientBrush>

            </Ellipse.Fill>
          </Ellipse>
          <Path x:Name="Arrow"
                Margin="0,0,3,0"
                HorizontalAlignment="Center"
                VerticalAlignment="Center"
                Data="M 6 0 L 0 6 L 6 12 Z">
            <Path.Fill>
              <SolidColorBrush Color="{DynamicResource GlyphColor}" />
            </Path.Fill>
          </Path>
        </Grid>
        <ControlTemplate.Triggers>
          <Trigger Property="Command"
                   Value="{x:Static NavigationCommands.BrowseForward}">
            <Setter TargetName="Arrow"
                    Property="Data"
                    Value="M 0 0 L 6 6 L 0 12 z" />
            <Setter TargetName="Arrow"
                    Property="Margin"
                    Value="3,0,0,0" />
          </Trigger>
        </ControlTemplate.Triggers>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

<!-- NavWin Menu Style -->
<Style x:Key="NavWinMenu"
       TargetType="{x:Type Menu}">
  <Setter Property="OverridesDefaultStyle"
          Value="true" />
  <Setter Property="KeyboardNavigation.TabNavigation"
          Value="None" />
  <Setter Property="IsMainMenu"
          Value="false" />
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type Menu}">
        <DockPanel IsItemsHost="true" />
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

<!-- NavWin Menu Header Style -->
<Style x:Key="NavWinHeaderMenuItem"
       TargetType="{x:Type MenuItem}">
  <Setter Property="OverridesDefaultStyle"
          Value="true" />
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type MenuItem}">
        <Grid>
          <Popup x:Name="PART_Popup"
                 Placement="Bottom"
                 VerticalOffset="2"
                 IsOpen="{TemplateBinding IsSubmenuOpen}"
                 AllowsTransparency="True"
                 Focusable="False"
                 PopupAnimation="Fade">
            <Border x:Name="SubMenuBorder"
                    Background="{DynamicResource MenuPopupBrush}"
                    BorderThickness="1">
              <Border.BorderBrush>
                <SolidColorBrush Color="{DynamicResource BorderMediumColor}" />
              </Border.BorderBrush>
              <StackPanel IsItemsHost="true"
                          Margin="2"
                          KeyboardNavigation.TabNavigation="Cycle"
                          KeyboardNavigation.DirectionalNavigation="Cycle" />
            </Border>
          </Popup>

          <Grid x:Name="Panel"
                Width="24"
                Background="Transparent"
                HorizontalAlignment="Right"
                VerticalAlignment="Stretch"
                d:IsHidden="True">

            <Border Visibility="Hidden"
                    x:Name="HighlightBorder"
                    BorderThickness="1"
                    CornerRadius="2">
              <Border.BorderBrush>
                <LinearGradientBrush StartPoint="0,0"
                                     EndPoint="0,1">
                  <LinearGradientBrush.GradientStops>
                    <GradientStopCollection>
                      <GradientStop Color="{DynamicResource BorderLightColor}"
                                    Offset="0.0" />
                      <GradientStop Color="{DynamicResource BorderDarkColor}"
                                    Offset="1.0" />
                    </GradientStopCollection>
                  </LinearGradientBrush.GradientStops>
                </LinearGradientBrush>

              </Border.BorderBrush>
              <Border.Background>
                <LinearGradientBrush StartPoint="0,0"
                                     EndPoint="0,1">
                  <LinearGradientBrush.GradientStops>
                    <GradientStopCollection>
                      <GradientStop Color="{DynamicResource ControlLightColor}" />
                      <GradientStop Color="{DynamicResource ControlMouseOverColor}"
                                    Offset="1.0" />
                    </GradientStopCollection>
                  </LinearGradientBrush.GradientStops>
                </LinearGradientBrush>

              </Border.Background>
            </Border>
            <Path x:Name="Arrow"
                  SnapsToDevicePixels="false"
                  HorizontalAlignment="Right"
                  VerticalAlignment="Center"
                  Margin="0,2,4,0"
                  StrokeLineJoin="Round"
                  Data="M 0 0 L 4 4 L 8 0 Z">
              <Path.Fill>
                <SolidColorBrush Color="{DynamicResource GlyphColor}" />
              </Path.Fill>
            </Path>
          </Grid>
        </Grid>
        <ControlTemplate.Triggers>
          <Trigger Property="IsHighlighted"
                   Value="true">
            <Setter TargetName="HighlightBorder"
                    Property="Visibility"
                    Value="Visible" />
          </Trigger>
          <Trigger Property="IsSubmenuOpen"
                   Value="true">
            <Setter TargetName="HighlightBorder"
                    Property="BorderBrush">
              <Setter.Value>
                <LinearGradientBrush StartPoint="0,0"
                                     EndPoint="0,1">
                  <GradientBrush.GradientStops>
                    <GradientStopCollection>
                      <GradientStop Color="{DynamicResource BorderDarkColor}"
                                    Offset="0.0" />
                      <GradientStop Color="{DynamicResource BorderMediumColor}"
                                    Offset="1.0" />
                    </GradientStopCollection>
                  </GradientBrush.GradientStops>
                </LinearGradientBrush>

              </Setter.Value>
            </Setter>
            <Setter Property="Background"
                    TargetName="HighlightBorder">
              <Setter.Value>

                <LinearGradientBrush EndPoint="0,1"
                                     StartPoint="0,0">
                  <GradientStop Color="{DynamicResource ControlLightColor}"
                                Offset="0" />
                  <GradientStop Color="{DynamicResource ControlPressedColor}"
                                Offset="0.984" />
                </LinearGradientBrush>
              </Setter.Value>
            </Setter>
          </Trigger>
        </ControlTemplate.Triggers>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

<!-- NavWin Menu Item Style -->

<Style x:Key="NavWinSubmenuItem"
       TargetType="{x:Type MenuItem}">
  <Setter Property="OverridesDefaultStyle"
          Value="true" />
  <Setter Property="Header"
          Value="{Binding (JournalEntry.Name)}" />
  <Setter Property="Command"
          Value="NavigationCommands.NavigateJournal" />
  <Setter Property="CommandTarget"
          Value="{Binding TemplatedParent, RelativeSource={RelativeSource AncestorType={x:Type Menu}}}" />
  <Setter Property="CommandParameter"
          Value="{Binding RelativeSource={RelativeSource Self}}" />
  <Setter Property="JournalEntryUnifiedViewConverter.JournalEntryPosition"
          Value="{Binding (JournalEntryUnifiedViewConverter.JournalEntryPosition)}" />
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type MenuItem}">
        <Border Name="Border"
                BorderThickness="1">
          <Grid x:Name="Panel"
                Background="Transparent"
                SnapsToDevicePixels="true"
                Height="35"
                Width="250">
            <Path x:Name="Glyph"
                  SnapsToDevicePixels="false"
                  Margin="7,5"
                  Width="10"
                  Height="10"
                  HorizontalAlignment="Left"
                  StrokeStartLineCap="Triangle"
                  StrokeEndLineCap="Triangle"
                  StrokeThickness="2">
              <Path.Stroke>
                <SolidColorBrush Color="{DynamicResource GlyphColor}" />
              </Path.Stroke>
            </Path>
            <ContentPresenter ContentSource="Header"
                              Margin="24,5,50,5" />
          </Grid>
        </Border>
        <ControlTemplate.Triggers>
          <Trigger Value="Current"
                   Property="JournalEntryUnifiedViewConverter.JournalEntryPosition">
            <Setter TargetName="Glyph"
                    Property="Data"
                    Value="M 0,5 L 2.5,8 L 7,3 " />
          </Trigger>
          <Trigger Property="IsHighlighted"
                   Value="true">
            <Setter Property="Background"
                    TargetName="Border">
              <Setter.Value>
                <LinearGradientBrush EndPoint="0.5,1"
                                     StartPoint="0.5,0">
                  <GradientStop Color="Transparent"
                                Offset="0" />
                  <GradientStop Color="{DynamicResource ControlMouseOverColor}"
                                Offset="1" />
                </LinearGradientBrush>
              </Setter.Value>
            </Setter>
            <Setter Property="BorderBrush"
                    TargetName="Border">
              <Setter.Value>
                <LinearGradientBrush EndPoint="0.5,1"
                                     StartPoint="0.5,0">
                  <GradientStop Color="{DynamicResource BorderMediumColor}"
                                Offset="0" />
                  <GradientStop Color="Transparent"
                                Offset="1" />
                </LinearGradientBrush>
              </Setter.Value>
            </Setter>
          </Trigger>
          <MultiTrigger>
            <MultiTrigger.Conditions>
              <Condition Property="IsHighlighted"
                         Value="true" />
              <Condition Value="Forward"
                         Property="JournalEntryUnifiedViewConverter.JournalEntryPosition" />
            </MultiTrigger.Conditions>
            <Setter TargetName="Glyph"
                    Property="Data"
                    Value="M 3 1 L 7 5 L 3 9 z" />
            <Setter TargetName="Glyph"
                    Property="Fill">
              <Setter.Value>
                <SolidColorBrush Color="{StaticResource GlyphColor}" />
              </Setter.Value>
            </Setter>
            <Setter TargetName="Glyph"
                    Property="Stroke"
                    Value="{x:Null}" />
          </MultiTrigger>
          <MultiTrigger>
            <MultiTrigger.Conditions>
              <Condition Property="IsHighlighted"
                         Value="true" />
              <Condition Value="Back"
                         Property="JournalEntryUnifiedViewConverter.JournalEntryPosition" />
            </MultiTrigger.Conditions>
            <Setter TargetName="Glyph"
                    Property="Data"
                    Value="M 7 1 L 3 5 L 7 9 z" />
            <Setter TargetName="Glyph"
                    Property="Fill">
              <Setter.Value>
                <SolidColorBrush Color="{StaticResource GlyphColor}" />
              </Setter.Value>
            </Setter>
            <Setter TargetName="Glyph"
                    Property="Stroke"
                    Value="{x:Null}" />
          </MultiTrigger>
        </ControlTemplate.Triggers>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

<!-- Merges Back and Forward Navigation Stacks -->

<JournalEntryUnifiedViewConverter x:Key="JournalEntryUnifiedViewConverter" />

<!-- SimpleStyles: NavigationWindow -->

<Style x:Key="{x:Type NavigationWindow}"
       TargetType="{x:Type NavigationWindow}">
  <Setter Property="SnapsToDevicePixels"
          Value="true" />
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type NavigationWindow}">
        <DockPanel>
          <DockPanel.Background>
            <SolidColorBrush Color="{DynamicResource WindowColor}" />
          </DockPanel.Background>
          <Border DockPanel.Dock="Top"
                  Height="30"
                  BorderThickness="1">
            <Border.BorderBrush>
              <SolidColorBrush Color="{DynamicResource BorderMediumColor}" />
            </Border.BorderBrush>
            <Grid>
              <Grid.Background>

                <LinearGradientBrush StartPoint="0,0"
                                     EndPoint="0,1">
                  <LinearGradientBrush.GradientStops>
                    <GradientStopCollection>
                      <GradientStop Color="{DynamicResource ControlLightColor}"
                                    Offset="0.0" />
                      <GradientStop Color="{DynamicResource ControlMediumColor}"
                                    Offset="1.0" />
                    </GradientStopCollection>
                  </LinearGradientBrush.GradientStops>
                </LinearGradientBrush>

              </Grid.Background>
              <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="16" />
                <ColumnDefinition Width="*" />
              </Grid.ColumnDefinitions>

              <Menu x:Name="NavMenu"
                    Grid.ColumnSpan="3"
                    Height="20"
                    Margin="1,0,0,0"
                    VerticalAlignment="Center"
                    Style="{StaticResource NavWinMenu}">
                <MenuItem Style="{StaticResource NavWinHeaderMenuItem}"
                          ItemContainerStyle="{StaticResource NavWinSubmenuItem}"
                          IsSubmenuOpen="{Binding (MenuItem.IsSubmenuOpen), 
                  Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}">
                  <MenuItem.ItemsSource>
                    <MultiBinding Converter="{StaticResource JournalEntryUnifiedViewConverter}">
                      <Binding RelativeSource="{RelativeSource TemplatedParent}"
                               Path="BackStack" />
                      <Binding RelativeSource="{RelativeSource TemplatedParent}"
                               Path="ForwardStack" />
                    </MultiBinding>
                  </MenuItem.ItemsSource>
                </MenuItem>
              </Menu>

              <Path Grid.Column="0"
                    SnapsToDevicePixels="false"
                    IsHitTestVisible="false"
                    Margin="2,1.5,0,1.5"
                    Grid.ColumnSpan="3"
                    StrokeThickness="1"
                    HorizontalAlignment="Left"
                    VerticalAlignment="Center"
                    Data="M22.5767,21.035 Q27,19.37 
                      31.424,21.035 A12.5,12.5,0,0,0,53.5,13
                      A12.5,12.5,0,0,0,37.765,0.926
                      Q27,4.93 16.235,0.926
                      A12.5,12.5,0,0,0,0.5,13 
                      A12.5,12.5,0,0,0,22.5767,21.035 z">
                <Path.Stroke>
                  <SolidColorBrush Color="{DynamicResource BorderMediumColor}" />
                </Path.Stroke>
                <Path.Fill>

                  <LinearGradientBrush EndPoint="0,1"
                                       StartPoint="0,0">
                    <GradientStop Color="{DynamicResource ControlMediumColor}"
                                  Offset="0" />

                    <GradientStop Color="{DynamicResource ControlDarkColor}"
                                  Offset="0.984" />
                  </LinearGradientBrush>
                </Path.Fill>
              </Path>
              <Button Style="{StaticResource NavWinButtonStyle}"
                      Command="NavigationCommands.BrowseBack"
                      Content="M 4 0 L 0 4 L 4 8 Z"
                      Margin="3,1.5,2,1.5"
                      Grid.Column="0" />
              <Button Style="{StaticResource NavWinButtonStyle}"
                      Command="NavigationCommands.BrowseForward"
                      Content="M 4 0 L 0 4 L 4 8 Z"
                      Margin="2,1.5,0,1.5"
                      Grid.Column="1" />
            </Grid>
          </Border>
          <Grid>
            <AdornerDecorator>
              <Border BorderThickness="1">
                <Border.BorderBrush>
                  <SolidColorBrush Color="{DynamicResource BorderMediumColor}" />
                </Border.BorderBrush>
                <ContentPresenter x:Name="PART_NavWinCP"
                                  ClipToBounds="true" />
              </Border>
            </AdornerDecorator>

            <ResizeGrip x:Name="WindowResizeGrip"
                        HorizontalAlignment="Right"
                        VerticalAlignment="Bottom"
                        Visibility="Collapsed"
                        IsTabStop="false" />
          </Grid>
        </DockPanel>
        <ControlTemplate.Triggers>
          <Trigger Property="ResizeMode"
                   Value="CanResizeWithGrip">
            <Setter TargetName="WindowResizeGrip"
                    Property="Visibility"
                    Value="Visible" />
          </Trigger>
        </ControlTemplate.Triggers>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>
<Style x:Key="{x:Type ResizeGrip}"
       TargetType="{x:Type ResizeGrip}">
  <Setter Property="OverridesDefaultStyle"
          Value="true" />
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type ResizeGrip}">
        <Border Background="Transparent"
                SnapsToDevicePixels="True"
                Width="16"
                Height="16">
          <Rectangle Margin="2">
            <Rectangle.Fill>
              <DrawingBrush Viewport="0,0,4,4"
                            ViewportUnits="Absolute"
                            Viewbox="0,0,8,8"
                            ViewboxUnits="Absolute"
                            TileMode="Tile">
                <DrawingBrush.Drawing>
                  <DrawingGroup>
                    <DrawingGroup.Children>
                      <GeometryDrawing Brush="#FFE8EDF9"
                                       Geometry="M 4 4 L 4 8 L 
                                                 8 8 L 8 4 z" />
                    </DrawingGroup.Children>
                  </DrawingGroup>
                </DrawingBrush.Drawing>
              </DrawingBrush>
            </Rectangle.Fill>
          </Rectangle>
        </Border>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>
<!--Control colors.-->
<Color x:Key="WindowColor">#FFE8EDF9</Color>
<Color x:Key="ContentAreaColorLight">#FFC5CBF9</Color>
<Color x:Key="ContentAreaColorDark">#FF7381F9</Color>

<Color x:Key="DisabledControlLightColor">#FFE8EDF9</Color>
<Color x:Key="DisabledControlDarkColor">#FFC5CBF9</Color>
<Color x:Key="DisabledForegroundColor">#FF888888</Color>

<Color x:Key="SelectedBackgroundColor">#FFC5CBF9</Color>
<Color x:Key="SelectedUnfocusedColor">#FFDDDDDD</Color>

<Color x:Key="ControlLightColor">White</Color>
<Color x:Key="ControlMediumColor">#FF7381F9</Color>
<Color x:Key="ControlDarkColor">#FF211AA9</Color>

<Color x:Key="ControlMouseOverColor">#FF3843C4</Color>
<Color x:Key="ControlPressedColor">#FF211AA9</Color>


<Color x:Key="GlyphColor">#FF444444</Color>
<Color x:Key="GlyphMouseOver">sc#1, 0.004391443, 0.002428215, 0.242281124</Color>

<!--Border colors-->
<Color x:Key="BorderLightColor">#FFCCCCCC</Color>
<Color x:Key="BorderMediumColor">#FF888888</Color>
<Color x:Key="BorderDarkColor">#FF444444</Color>

<Color x:Key="PressedBorderLightColor">#FF888888</Color>
<Color x:Key="PressedBorderDarkColor">#FF444444</Color>

<Color x:Key="DisabledBorderLightColor">#FFAAAAAA</Color>
<Color x:Key="DisabledBorderDarkColor">#FF888888</Color>

<Color x:Key="DefaultBorderBrushDarkColor">Black</Color>

<!--Control-specific resources.-->
<Color x:Key="HeaderTopColor">#FFC5CBF9</Color>
<Color x:Key="DatagridCurrentCellBorderColor">Black</Color>
<Color x:Key="SliderTrackDarkColor">#FFC5CBF9</Color>

<Color x:Key="NavButtonFrameColor">#FF3843C4</Color>

<LinearGradientBrush x:Key="MenuPopupBrush"
                     EndPoint="0.5,1"
                     StartPoint="0.5,0">
  <GradientStop Color="{DynamicResource ControlLightColor}"
                Offset="0" />
  <GradientStop Color="{DynamicResource ControlMediumColor}"
                Offset="0.5" />
  <GradientStop Color="{DynamicResource ControlLightColor}"
                Offset="1" />
</LinearGradientBrush>

<LinearGradientBrush x:Key="ProgressBarIndicatorAnimatedFill"
                     StartPoint="0,0"
                     EndPoint="1,0">
  <LinearGradientBrush.GradientStops>
    <GradientStopCollection>
      <GradientStop Color="#000000FF"
                    Offset="0" />
      <GradientStop Color="#600000FF"
                    Offset="0.4" />
      <GradientStop Color="#600000FF"
                    Offset="0.6" />
      <GradientStop Color="#000000FF"
                    Offset="1" />
    </GradientStopCollection>
  </LinearGradientBrush.GradientStops>
</LinearGradientBrush>

 

 

 


 

 

 

 이 글의 내용은 아래의 사이트에서 기초합니다.

https://docs.microsoft.com/ko-kr/dotnet/desktop/wpf/controls/navigationwindow-styles-and-templates?view=netframeworkdesktop-4.8 

 

NavigationWindow 스타일 및 템플릿 - WPF .NET Framework

NavigationWindow 스타일 및 템플릿 아티클 05/04/2022 읽는 데 6분 걸림 기여자 1명 이 문서의 내용 --> 이 항목에서는 NavigationWindow 컨트롤의 스타일 및 템플릿을 설명합니다. 기본값을 수정할 수 있습니

docs.microsoft.com

 

반응형

'프로그램 개발 > WPF: Style&Template' 카테고리의 다른 글

NavigationWindow③  (0) 2022.06.14
NavigationWindow②  (0) 2022.06.13
Menu④  (0) 2022.06.09
Menu③  (0) 2022.06.08
Menu②  (0) 2022.06.07