Share via


NavigationWindow ControlTemplate Example

Controls in Windows Presentation Foundation (WPF) have a ControlTemplate that contains the visual tree of that control. You can change the structure and appearance of a control by modifying the ControlTemplate of that control. There is no way to replace only part of the visual tree of a control; to change the visual tree of a control you must set the Template property of the control to its new and complete ControlTemplate.

This topic shows the ControlTemplate of the WPF NavigationWindow control.

This topic contains the following sections.

  • Prerequisites
  • NavigationWindow ControlTemplate Example
  • Related Topics

Prerequisites

To run the examples in this topic, you should understand how to write WPF applications. For more information, see Get Started Using Windows Presentation Foundation. You should also understand how styles are used in WPF. For more information, see Styling and Templating.

While this example contains all of the elements that are defined in the ControlTemplate of a NavigationWindow by default, the specific values should be thought of as examples.

<Style x:Key="NavWinButtonStyle" TargetType="Button">
  <Setter Property="OverridesDefaultStyle" Value="true"/>
  <Setter Property="Command" Value="NavigationCommands.BrowseBack"/>
  <Setter Property="Focusable" Value="false"/>
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="Button">
        <Grid>
          <Ellipse 
            Name="Ellipse" 
            Fill="{StaticResource NormalBrush}"
            Stroke="{StaticResource NormalBorderBrush}"
            StrokeThickness="1" 
            Width="24"
            Height="24"/>

          <Path 
            x:Name="Arrow"
            Margin="0,0,3,0"
            Fill="{StaticResource GlyphBrush}"
            HorizontalAlignment="Center"
            VerticalAlignment="Center"
            Data="M 6 0 L 0 6 L 6 12 Z"/>
        </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>
          <Trigger Property="IsMouseOver" Value="True">
            <Setter TargetName="Ellipse"
                    Property="Fill" Value="{StaticResource DarkBrush}"/>
          </Trigger>
          <Trigger Property="IsPressed" Value="true">
            <Setter TargetName="Ellipse"
                    Property="Fill" Value="{StaticResource PressedBrush}" />
            <Setter TargetName="Ellipse"
                    Property="Stroke" Value="{StaticResource PressedBorderBrush}" />
          </Trigger>
          <Trigger Property="IsEnabled" Value="false">
            <Setter TargetName="Ellipse"
                    Property="Fill" Value="{StaticResource DisabledBackgroundBrush}"/>
            <Setter TargetName="Arrow"
                    Property="Fill" Value="{StaticResource DisabledForegroundBrush}"/>
          </Trigger>
        </ControlTemplate.Triggers>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

<!-- NavWin Menu Style -->

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

<!-- NavWin Menu Header Style -->

<Style x:Key="NavWinHeaderMenuItem" TargetType="MenuItem">
  <Setter Property="OverridesDefaultStyle" Value="true"/>
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="MenuItem">
        <Grid>
          <Popup x:Name="PART_Popup"
            Placement="Bottom"
            VerticalOffset="2"
            IsOpen="{TemplateBinding IsSubmenuOpen}"
            AllowsTransparency="True" 
            Focusable="False"
            PopupAnimation="Fade">
            <Border Name="SubMenuBorder"
              Background="{StaticResource WindowBackgroundBrush}"
              BorderThickness="1"
              BorderBrush="{StaticResource SolidBorderBrush}">
              <StackPanel IsItemsHost="true"
                Margin="2"
                KeyboardNavigation.TabNavigation="Cycle"
                KeyboardNavigation.DirectionalNavigation="Cycle"/>
            </Border>
          </Popup>

          <Grid x:Name="Panel" 
            Width="24" 
            Background="Transparent"
            HorizontalAlignment="Right" >

            <Border Visibility="Hidden" 
              Name="HighlightBorder" 
              BorderThickness="1" 
              BorderBrush="{StaticResource NormalBorderBrush}" 
              Background="{StaticResource NormalBrush}" 
              CornerRadius="2" />
            <Path x:Name="Arrow"
              SnapsToDevicePixels="false"
              HorizontalAlignment="Right"
              VerticalAlignment="Center"
              Margin="0,2,4,0"
              Fill="{StaticResource GlyphBrush}"
              StrokeLineJoin="Round"
              Data="M 0 0 L 4 4 L 8 0 Z"/>
          </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="Background" Value="{StaticResource PressedBrush}" />
            <Setter TargetName="HighlightBorder" Property="BorderBrush" Value="{StaticResource PressedBorderBrush}" />
          </Trigger>
          <Trigger Property="IsEnabled" Value="false">
            <Setter TargetName="Arrow" Property="Fill"  Value="{StaticResource DisabledForegroundBrush}"/>
          </Trigger>
        </ControlTemplate.Triggers>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

<!-- NavWin Menu Item Style -->

<Style x:Key="NavWinSubmenuItem" TargetType="MenuItem">
  <Setter Property="OverridesDefaultStyle" Value="true"/>
  <Setter Property="Header" Value="{Binding Path=(JournalEntry.Name)}"/>
  <Setter Property="Command" Value="NavigationCommands.NavigateJournal"/>
  <Setter Property="CommandTarget"
          Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type Menu}},
          Path=TemplatedParent}"/>
  <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}">
        <Grid Name="Panel"
          Background="Transparent"
          SnapsToDevicePixels="true">
          <Path Name="Glyph"
            SnapsToDevicePixels="false"
            Margin="7,5"
            Width="10"
            Height="10"
            HorizontalAlignment="Left"
            StrokeStartLineCap="Triangle"
            StrokeEndLineCap="Triangle"
            StrokeThickness="2"
            Stroke="{StaticResource GlyphBrush}" />

          <ContentPresenter ContentSource="Header"
            Margin="24,5,50,5"/>
        </Grid>
        <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 TargetName="Panel" Property="Background"
                    Value="{StaticResource SelectedBackgroundBrush}"/>
          </Trigger>
          <MultiTrigger>
            <MultiTrigger.Conditions>
              <Condition Property="MenuItem.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"
                    Value="{StaticResource GlyphBrush}"/>
            <Setter TargetName="Glyph" Property="Stroke"
                    Value="{x:Null}"/>
          </MultiTrigger>
          <MultiTrigger>
            <MultiTrigger.Conditions>
              <Condition Property="MenuItem.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" Value="{StaticResource GlyphBrush}"/>
            <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="NavigationWindow">
  <Setter Property="SnapsToDevicePixels" Value="true"/>
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="NavigationWindow">
        <DockPanel  Background="{StaticResource WindowBackgroundBrush}">
          <Grid Background="{StaticResource LightBrush}"
            DockPanel.Dock="Top"
            Height="30">
            <Grid.ColumnDefinitions>
              <ColumnDefinition Width="Auto"/>
              <ColumnDefinition Width="Auto"/>
              <ColumnDefinition Width="16"/>
              <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>

            <Menu 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 Path=(MenuItem.IsSubmenuOpen),
                Mode=TwoWay,RelativeSource={RelativeSource TemplatedParent}}">
                <MenuItem.ItemsSource>
                  <MultiBinding Converter="{StaticResource JournalEntryUnifiedViewConverter}">
                    <MultiBinding.Bindings>
                      <Binding RelativeSource="{RelativeSource TemplatedParent}" 
                        Path="BackStack" />
                      <Binding RelativeSource="{RelativeSource TemplatedParent}" 
                        Path="ForwardStack" />
                    </MultiBinding.Bindings>
                  </MultiBinding>
                </MenuItem.ItemsSource>
              </MenuItem>
            </Menu>

            <Path Grid.Column="0" 
              SnapsToDevicePixels="false"
              IsHitTestVisible="false"
              Margin="2,0,0,0"
              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"
              Fill="{StaticResource PressedBrush}"
              Stroke="{StaticResource LightBorderBrush}"/>
            <Button Style="{StaticResource NavWinButtonStyle}"
              Command="NavigationCommands.BrowseBack"
              Content="M 4 0 L 0 4 L 4 8 Z"
              Margin="3,0,2,0" 
              Grid.Column="0"/>
            <Button Style="{StaticResource NavWinButtonStyle}"
              Command="NavigationCommands.BrowseForward"
              Content="M 4 0 L 0 4 L 4 8 Z"
              Margin="2,0,0,0" 
              Grid.Column="1"/>
          </Grid>
          <Grid>
            <AdornerDecorator>
              <ContentPresenter Name="PART_NavWinCP" 
                                ClipToBounds="true"/>
            </AdornerDecorator>

            <ResizeGrip x:Name="WindowResizeGrip"
              HorizontalAlignment="Right"
              VerticalAlignment="Bottom"
              Visibility="Collapsed" 
              IsTabStop="false"/>
          </Grid>
        </DockPanel>
        <ControlTemplate.Triggers>
          <MultiTrigger>
            <MultiTrigger.Conditions>
              <Condition Property="CanGoForward" Value="false"/>
              <Condition Property="CanGoBack" Value="false"/>
            </MultiTrigger.Conditions>
            <Setter TargetName="NavMenu" Property="IsEnabled" Value="false"/>
          </MultiTrigger>
          <Trigger Property="ResizeMode" Value="CanResizeWithGrip">
            <Setter TargetName="WindowResizeGrip" Property="Visibility" Value="Visible"/>
          </Trigger>
        </ControlTemplate.Triggers>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

The above example uses the following resources:

<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="#AAA"
                        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>

  ...

<!-- Fill Brushes -->

<LinearGradientBrush x:Key="NormalBrush" StartPoint="0,0" EndPoint="0,1">
  <GradientBrush.GradientStops>
    <GradientStopCollection>
      <GradientStop Color="#FFF" Offset="0.0"/>
      <GradientStop Color="#CCC" Offset="1.0"/>
    </GradientStopCollection>
  </GradientBrush.GradientStops>
</LinearGradientBrush>

<LinearGradientBrush x:Key="HorizontalNormalBrush" StartPoint="0,0" EndPoint="1,0">
  <GradientBrush.GradientStops>
    <GradientStopCollection>
      <GradientStop Color="#FFF" Offset="0.0"/>
      <GradientStop Color="#CCC" Offset="1.0"/>
    </GradientStopCollection>
  </GradientBrush.GradientStops>
</LinearGradientBrush>

<LinearGradientBrush x:Key="LightBrush" StartPoint="0,0" EndPoint="0,1">
  <GradientBrush.GradientStops>
    <GradientStopCollection>
      <GradientStop Color="#FFF" Offset="0.0"/>
      <GradientStop Color="#EEE" Offset="1.0"/>
    </GradientStopCollection>
  </GradientBrush.GradientStops>
</LinearGradientBrush>

<LinearGradientBrush x:Key="HorizontalLightBrush" StartPoint="0,0" EndPoint="1,0">
  <GradientBrush.GradientStops>
    <GradientStopCollection>
      <GradientStop Color="#FFF" Offset="0.0"/>
      <GradientStop Color="#EEE" Offset="1.0"/>
    </GradientStopCollection>
  </GradientBrush.GradientStops>
</LinearGradientBrush>

<LinearGradientBrush x:Key="DarkBrush" StartPoint="0,0" EndPoint="0,1">
  <GradientBrush.GradientStops>
    <GradientStopCollection>
      <GradientStop Color="#FFF" Offset="0.0"/>
      <GradientStop Color="#AAA" Offset="1.0"/>
    </GradientStopCollection>
  </GradientBrush.GradientStops>
</LinearGradientBrush>

<LinearGradientBrush x:Key="PressedBrush" StartPoint="0,0" EndPoint="0,1">
  <GradientBrush.GradientStops>
    <GradientStopCollection>
      <GradientStop Color="#BBB" Offset="0.0"/>
      <GradientStop Color="#EEE" Offset="0.1"/>
      <GradientStop Color="#EEE" Offset="0.9"/>
      <GradientStop Color="#FFF" Offset="1.0"/>
    </GradientStopCollection>
  </GradientBrush.GradientStops>
</LinearGradientBrush>

<SolidColorBrush x:Key="DisabledForegroundBrush" Color="#888" />

<SolidColorBrush x:Key="DisabledBackgroundBrush" Color="#EEE" />

<SolidColorBrush x:Key="WindowBackgroundBrush" Color="#FFF" />

<SolidColorBrush x:Key="SelectedBackgroundBrush" Color="#DDD" />

<!-- Border Brushes -->

<LinearGradientBrush x:Key="NormalBorderBrush" StartPoint="0,0" EndPoint="0,1">
  <GradientBrush.GradientStops>
    <GradientStopCollection>
      <GradientStop Color="#CCC" Offset="0.0"/>
      <GradientStop Color="#444" Offset="1.0"/>
    </GradientStopCollection>
  </GradientBrush.GradientStops>
</LinearGradientBrush>

<LinearGradientBrush x:Key="HorizontalNormalBorderBrush" StartPoint="0,0" EndPoint="1,0">
  <GradientBrush.GradientStops>
    <GradientStopCollection>
      <GradientStop Color="#CCC" Offset="0.0"/>
      <GradientStop Color="#444" Offset="1.0"/>
    </GradientStopCollection>
  </GradientBrush.GradientStops>
</LinearGradientBrush>

<LinearGradientBrush x:Key="DefaultedBorderBrush" StartPoint="0,0" EndPoint="0,1">
  <GradientBrush.GradientStops>
    <GradientStopCollection>
      <GradientStop Color="#777" Offset="0.0"/>
      <GradientStop Color="#000" Offset="1.0"/>
    </GradientStopCollection>
  </GradientBrush.GradientStops>
</LinearGradientBrush>

<LinearGradientBrush x:Key="PressedBorderBrush" StartPoint="0,0" EndPoint="0,1">
  <GradientBrush.GradientStops>
    <GradientStopCollection>
      <GradientStop Color="#444" Offset="0.0"/>
      <GradientStop Color="#888" Offset="1.0"/>
    </GradientStopCollection>
  </GradientBrush.GradientStops>
</LinearGradientBrush>

<SolidColorBrush x:Key="DisabledBorderBrush" Color="#AAA" />

<SolidColorBrush x:Key="SolidBorderBrush" Color="#888" />

<SolidColorBrush x:Key="LightBorderBrush" Color="#AAA" />

<!-- Miscellaneous Brushes -->
<SolidColorBrush x:Key="GlyphBrush" Color="#444" />

<SolidColorBrush x:Key="LightColorBrush" Color="#DDD" />

For the complete sample, see Styling with ControlTemplates Sample.

See Also

Concepts

NavigationWindow ControlTemplate Example
Guidelines for Designing Stylable Controls

Other Resources

ControlTemplate Examples