Книги онлайн и без регистрации » Разная литература » Язык программирования C#9 и платформа .NET5 - Эндрю Троелсен

Язык программирования C#9 и платформа .NET5 - Эндрю Троелсен

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 351 352 353 354 355 356 357 358 359 ... 407
Перейти на страницу:
на экране. Внутри любого визуального дерева будут находиться полные детали шаблонов и стилей, используемых для визуализации каждого объекта, включая все необходимые рисунки, фигуры, визуальные объекты и объекты анимации.

Полезно уяснить разницу между логическим и визуальным деревьями, потому что при построении специального шаблона элемента управления на самом деле производится замена всего или части стандартного визуального дерева элемента управления собственным вариантом. Следовательно, если нужно, чтобы элемент управления Button визуализировался в виде звездообразной фигуры, тогда можно определить новый шаблон такого рода и подключить его к визуальному дереву Button. Логически тип остается тем же типом Button, поддерживая все ожидаемые свойства, методы и события. Но визуально он выглядит совершенно по-другому. Один лишь упомянутый факт делает WPF исключительно полезным API-интерфейсом, поскольку другие инструментальные наборы для создания кнопки звездообразной формы потребовали бы построения совершенно нового класса. В инфраструктуре WPF понадобится просто определить новую разметку.

На заметку! Элементы управления WPF часто описывают как лишенные внешности. Это относится к тому факту, что внешний вид элемента управления WPF совершенно не зависит от его поведения и допускает настройку.

Программное инспектирование логического дерева

Хотя анализ логического дерева окна во время выполнения — не слишком распространенное действие при программировании с применением WPF, полезно упомянуть о том, что в пространстве имен System.Windows определен класс LogicalTreeHelper, который позволяет инспектировать структуру логического дерева во время выполнения. Для иллюстрации связи между логическими деревьями, визуальными деревьями и шаблонами элементов управления создайте новый проект приложения WPF по имени TreesAndTemplatesApp.

Замените элемент Grid приведенной ниже разметкой, которая содержит два элемента управления Button и крупный допускающий только чтение элемент TextBox с включенными линейками прокрутки. Создайте в IDE-среде обработчики событий Click для каждой кнопки. Вот результирующая разметка XAML:

<DockPanel LastChildFill="True">

  <Border Height="50" DockPanel.Dock="Top" BorderBrush="Blue">

    <StackPanel Orientation="Horizontal">

      <Button x:Name="btnShowLogicalTree" Content="Logical Tree of Window"

          Margin="4" BorderBrush="Blue" Height="40"

          Click="btnShowLogicalTree_Click"/>

      <Button x:Name="btnShowVisualTree" Content="Visual Tree of Window"

          BorderBrush="Blue" Height="40" Click="btnShowVisualTree_Click"/>

    </StackPanel>

  </Border>

  <TextBox x:Name="txtDisplayArea" Margin="10"

    Background="AliceBlue" IsReadOnly="True"

    BorderBrush="Red" VerticalScrollBarVisibility="Auto"

    HorizontalScrollBarVisibility="Auto" />

</DockPanel>

Внутри файла кода C# определите переменную-член _dataToShow типа string. В обработчике события Click объекта btnShowLogicalTree вызовите вспомогательную функцию,которая продолжит вызывать себя рекурсивно с целью заполнения строковой переменной логическим деревом Window. Для этого будет вызван статический метод GetChildren() объекта LogicalTreeHelper. Ниже показан необходимый код:

private string _dataToShow=string.Empty;

private void btnShowLogicalTree_Click(object sender, RoutedEventArgs e)

{

  _dataToShow="";

  BuildLogicalTree(0, this);

  txtDisplayArea.Text=_dataToShow;

}

void BuildLogicalTree(int depth, object obj)

{

  // Добавить имя типа к переменной-члену _dataToShow.

  _dataToShow +=new string(' ', depth) + obj.GetType().Name + "n";

  // Если элемент - не DependencyObject, тогда пропустить его.

  if (!(obj is DependencyObject))

    return;

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

  foreach (var child in LogicalTreeHelper.GetChildren((DependencyObject)obj))

  {

      BuildLogicalTree(depth + 5, child);

  }

}

private void btnShowVisualTree_Click(

  object sender, RoutedEventArgs e)

{

}

После запуска приложения и щелчка на кнопке Logical Tree of Window (Логическое дерево окна) в текстовой области отобразится древовидное представление, которое выглядит почти как точная копия исходной разметки XAML (рис. 27.10).

Программное инспектирование визуального дерева

Визуальное дерево объекта Window также можно инспектировать во время выполнения с использованием класса VisualTreeHelper из пространства имен System.Windows.Media. Далее приведена реализация обработчика события Click для второго элемента управления Button (btnShowVisualTree), которая выполняет похожую рекурсивную логику с целью построения текстового представления визуального дерева:

using System.Windows.Media;

private void btnShowVisualTree_Click(object sender, RoutedEventArgs e)

{

  _dataToShow="";

  BuildVisualTree(0, this);

  txtDisplayArea.Text=_dataToShow;

}

void BuildVisualTree(int depth, DependencyObject obj)

{

  // Добавить имя типа к переменной-члену _dataToShow.

  _dataToShow +=new string(' ', depth) + obj.GetType().Name + "n";

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

  for (int i=0; i < VisualTreeHelper.GetChildrenCount(obj); i++)

   {

    BuildVisualTree(depth + 1, VisualTreeHelper.GetChild(obj, i));

  }

}

На рис. 27.11 видно, что визуальное дерево открывает доступ к нескольким низкоуровневым агентам визуализации, таким как ContentPresenter, AdornerDecorator, TextBoxLineDrawingVisual и т.д.

Программное инспектирование стандартного шаблона элемента управления

Вспомните, что визуальное дерево применяется инфраструктурой WPF для выяснения, каким образом визуализировать элемент Window и все содержащиеся в нем элементы. Каждый элемент управления WPF хранит собственный набор команд визуализации внутри своего стандартного шаблона. С точки зрения программирования любой шаблон может быть представлен как экземпляр класса ControlTemplate. Кроме того, стандартный шаблон элемента управления можно получить через свойство Template:

// Получить стандартный шаблон элемента Button.

Button myBtn=new Button();

ControlTemplate template=myBtn.Template;

Подобным же образом можно создать в коде новый объект ControlTemplate и подключить его к свойству Template элемента управления:

// Подключить новый шаблон для использования в кнопке.

Button myBtn=new Button();

ControlTemplate customTemplate=new ControlTemplate();

// Предположим, что этот метод добавляет весь код для звездообразного шаблона.

MakeStarTemplate(customTemplate);

myBtn.Template=customTemplate;

Наряду с тем, что новый шаблон можно строить в коде, намного чаще это делается в разметке XAML. Тем не менее, прежде чем приступить к построению собственных шаблонов, завершите текущий пример и добавьте возможность просмотра стандартного шаблона для элемента управления WPF во время выполнения, что может оказаться полезным способом ознакомления с общей структурой шаблона  Добавьте в разметку окна новую панель StackPanel с элементами управления; она стыкована с левой стороной главной панели DockPanel (находится прямо перед элементом <TextBox>) и определена следующим образом:

<Border DockPanel.Dock="Left" Margin="10" BorderBrush="DarkGreen"

    BorderThickness="4" Width="358">

  <StackPanel>

    <Label Content="Enter Full Name of WPF Control" Width="340"

        FontWeight="DemiBold" />

    <TextBox x:Name="txtFullName" Width="340" BorderBrush="Green"

1 ... 351 352 353 354 355 356 357 358 359 ... 407
Перейти на страницу:

Комментарии
Минимальная длина комментария - 20 знаков. В коментария нецензурная лексика и оскорбления ЗАПРЕЩЕНЫ! Уважайте себя и других!
Комментариев еще нет. Хотите быть первым?