protected override Visual GetVisualChild(int index)

{

  // Значение должно быть больше нуля, поэтому разумно это проверить.

  if (index < 0 || index >= theVisuals.Count)

  {

     throw new ArgumentOutOfRangeException();

  }

  return theVisuals[index];

}

Теперь вы располагаете достаточной функциональностью, чтобы протестировать специальный класс. Модифицируйте описание XAML элемента Window, добавив в существующий контейнер StackPanel один объект CustomVisualFrameworkElement. Это потребует создания специального пространства имен XML, которое отображается на пространство имен .NET Core.

  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

  xmlns:local="clr-namespace:RenderingWithVisuals"

  Title="Fun with the Visual Layer" Height="350" Width="525"

  Loaded="Window_Loaded" WindowStartupLocation="CenterScreen">

   

     

      

   

Результат выполнения программы показан на рис. 26.15.

<p id="AutBody_Root1204"><strong>Реагирование на операции проверки попадания</strong></p>

Поскольку класс DrawingVisual не располагает инфраструктурой UIElement или FrameworkElement, необходимо программно добавить возможность реагирования на операции проверки попадания. Благодаря концепции логического и визуального деревьев на визуальном уровне делать это очень просто. Оказывается, что в результате написания блока XAML по существу строится логическое дерево элементов. Однако с каждым логическим деревом связано намного более развитое описание, известное как визуальное дерево, которое содержит низкоуровневые инструкции визуализации.

Упомянутые деревья подробно рассматриваются в главе 27, а сейчас достаточно знать, что до тех пор, пока специальные визуальные объекты не будут зарегистрированы в таких структурах данных, выполнять операции проверки попадания невозможно. К счастью, контейнер VisualCollection обеспечивает регистрацию автоматически (вот почему в аргументе конструктора необходимо передавать ссылку на специальный элемент FrameworkElement).

Измените код класса CustomVisualFrameworkElement для обработки события MouseDown в конструкторе класса с применением стандартного синтаксиса С#:

this.MouseDown += CustomVisualFrameworkElement_MouseDown;

Реализация данного обработчика будет вызывать метод VisualTreeHelper.HitTest() с целью выяснения, находится ли курсор мыши внутри границ одного из визуальных объектов. Для этого в одном из параметров метода HitTest() указывается делегат HitTestResultCallback, который будет выполнять вычисления. Добавьте в класс CustomVisualFrameworkElement следующие методы:

void CustomVisualFrameworkElement_MouseDown(object sender, MouseButtonEventArgs e)

{

  // Выяснить, где пользователь выполнил щелчок.

  Point pt = e.GetPosition((UIElement)sender);

  // Вызвать вспомогательную функцию через делегат, чтобы

  // посмотреть, был ли совершен щелчок на визуальном объекте.

  VisualTreeHelper.HitTest(this, null,

  new HitTestResultCallback(myCallback), new PointHitTestParameters(pt));

}

public HitTestResultBehavior myCallback(HitTestResult result)

{

    // Если щелчок был совершен на визуальном объекте, то

    // переключиться между скошенной и нормальной визуализацией.

    if (result.VisualHit.GetType() == typeof(DrawingVisual))

    {

      if (((DrawingVisual)result.VisualHit).Transform == null)

      {

         ((DrawingVisual)result.VisualHit).Transform = new SkewTransform(7, 7);

      }

      else

      {

         ((DrawingVisual)result.VisualHit).Transform = null;

    }

  }

Перейти на страницу:

Похожие книги