Шаблоны элементов управления

Логическое и визуальное дерево

Последнее обновление: 15.02.2016

Несмотря на то, что стили существенно облегчают манипулирование внешним видом элементов управления, гораздо более сильным средством в плане визуализации являются шаблоны. В отличие от стилей шаблоны помогают полностью менять модель визуализации элемента. Чтобы понять шаблоны, необходимо осознать общую концепцию визуализации в WPF.

Визуализация в WPF тесно связана с такими понятиями как логическое и визуальное дерево. Эти деревья являются своего рода каркасом приложения. Так мы можем представить приложение как некий набор вложенных элементов. Возьмем, к примеру, следующую простейшую разметку xaml:

<Window x:Class="ControlsTemplateApp.MainWindow"
        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:ControlsTemplateApp"
        mc:Ignorable="d"
        Title="MainWindow" Height="250" Width="300">
    <Grid>
        <Button x:Name="myButton">Hello</Button>
    </Grid>
</Window>

Структуру элементов здесь можно представить следующей схемой:

Логическое дерево в WPF

То есть в Window есть Grid, в Gride - элемент Button, в кнопке в качестве содержимого установлен некоторый текст в виде объекта String. В итоге получается некое дерево элементов, которое называется логическим. В WPF оно представлено классом System.Windows.LogicalTreeHelper. Логическое дерево имеет дело с визуализацией как таковой, оно образует модель доступа к дочерним элементам.

От него отличается визуальное дерево, представленное классом System.Windows.Media.VisualTreeHelper. Так, визуальное дерево для вышеприведенной разметки xaml будет выглядеть следующим образом:

Visual Tree в WPF

Визуальное дерево получается гораздо сложнее, оно показывает, как с визуальной точки зрения устроен элемент, из каких частей он состоит.

Visual Studio имеет встроенные средства для просмотра визуального дерева элементов. Для этого нам надо запустить проект в режиме отладки и в меню выбрать пункт Debug -> Windows -> Live Visual Tree. После нажатия на этот пункт Visual Studio откроет окно с визуальным деревом, в котором мы можем посмотреть, как устроен элемент:

Визуальное дерево в Visual Studio в WPF

Если мы нажмем правой кнопкой мыши на элемент в этом дереве и в контекстном меню выберем пункт Show Properties, справа в Visual Studio откроется окно свойств для этого элемента.

Визуальное дерево элемента управления опредлеляет, как будет выглядеть этот элемент или иными словами его шаблон. Шаблон элемента - это своего рода визуальный скелет элемента управления. Например, для элемента Button упрощенно шаблон выглядит следующим образом:

<Style TargetType="Button">
  <Setter Property="SnapsToDevicePixels" Value="true"/>
  <Setter Property="OverridesDefaultStyle" Value="true"/>
  <Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}"/>
  <Setter Property="MinHeight" Value="23"/>
  <Setter Property="MinWidth" Value="75"/>
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="Button">
        <Border 
          x:Name="Border"  
          CornerRadius="2" 
          BorderThickness="1"
          Background="{StaticResource NormalBrush}"
          BorderBrush="{StaticResource NormalBorderBrush}">
          <ContentPresenter 
            Margin="2"
            HorizontalAlignment="Center"
            VerticalAlignment="Center"
            RecognizesAccessKey="True"/>
        </Border>
        <ControlTemplate.Triggers>
          <Trigger Property="IsKeyboardFocused" Value="true">
            <Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource DefaultedBorderBrush}" />
          </Trigger>
          <Trigger Property="IsDefaulted" Value="true">
            <Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource DefaultedBorderBrush}" />
          </Trigger>
          <Trigger Property="IsMouseOver" Value="true">
            <Setter TargetName="Border" Property="Background" Value="{StaticResource DarkBrush}" />
          </Trigger>
          <Trigger Property="IsPressed" Value="true">
            <Setter TargetName="Border" Property="Background" Value="{StaticResource PressedBrush}" />
            <Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource PressedBorderBrush}" />
          </Trigger>
          <Trigger Property="IsEnabled" Value="false">
            <Setter TargetName="Border" Property="Background" Value="{StaticResource DisabledBackgroundBrush}" />
            <Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource DisabledBorderBrush}" />
            <Setter Property="Foreground" Value="{StaticResource DisabledForegroundBrush}"/>
          </Trigger>
        </ControlTemplate.Triggers>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

Полное описание шаблона кнопки можно найти по ссылке https://msdn.microsoft.com/en-us/library/ms753328%28v=vs.100%29.aspx.

Здесь мы можем увидеть, что сам шаблон задается с помощью стиля при определении сеттера для свойства Template. Чтобы определить сам, шаблон, применяется элемент ControlTemplate. И как раз в этом элементе мы можем увидеть и элемент Border, и элемент ContentPresenter, которые составляют визуальное дерево кнопки.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850