Упражнение 9. Разработка собственного менеджера размещения MyPanel
Предположим, что некоторые элементы управления мы хотим расположить равномерно по кругу с соответствующим угловым поворотом каждого из них. Это нестандартная задача и для ее решения типовых менеджеров размещения разработчиками не создано, зато предусмотрены возможности выполнить эту работу самостоятельно. Вряд ли нам понадобится в будущем это делать, но познакомиться стоит, чтобы знать, что такое возможно.
Все стандартные панели WPF наследуют абстрактному базовому классу Panel и наш собственный менеджер тоже должен наследовать этот библиотечный класс. Класс Panel, в свою очередь, наследует от класса UIElement, поэтому наш класс расширения приобретет от своих предков все необходимое. Класс Panel является такой вершиной цепочки наследования, которая включает в себя все паттерны (образец, кирпичик, строительный блок, базовый функциональный объект), необходимые для разработки любых менеджеров размещения. В нашем случае в классе расширения нам останется только перекрыть пару виртуальных методов.
Та часть объектной модели UIElement, которая относится к менеджеру размещения, довольно проста. Методы Measure, MeasureCore, Arrange и ArrangeCore реализуют два этапа размещения, а свойство Visibility говорит, должен ли потомок отображаться и учитываться при размещении.
Свойство Visibility позволяет задать три способа участия дочернего элемента в размещении. По умолчанию оно равно Visible: элемент отображается и занимает место на экране. При значении Hidden элемент скрыт, но место на экране занимает. При Collapsed дочерний элемент не отображается и место на экране не занимает.
Механизм взаимодействия размещаемого дочернего элемента и менеджера размещения состоит из двух частей:
- контракта, описывающего, как элемент принимает участие в размещении
- набора реализаций этого контракта
Никакого встроенного размещения нет, все конкретные способы размещения построены по принципу расширения базовых классов.
Все элементы WPF, включая и менеджеры размещения, адаптируются к своему содержимому. Эта концепция применяется на всех уровнях построения пользовательского интерфейса: окна могут подгонять свой размер под находящиеся в них элементы, кнопки - подстраиваться под надписи на них, текстовые поля - изменять свой размер так, чтобы поместились все символы.
Менеджеры реализуют двухэтапное размещение своих дочерних элементов: измерение и установка. Вначале менеджер опрашивает каждого из своих дочерних элементов на предмет того, какой фактический размер тот предпочитает, чтобы полностью показать свое содержимое на экране. Это этап измерения. Затем менеджер соотносит эту информацию со своими настройками и возможностями, сколько он может вместить, и приступает к этапу установки.
В ходе установки родитель безусловно требует от каждого из своих дочерних элементов, чтобы тот установил определенный размер и положение. Эта модель позволяет родителю и потомку договариваться о месте на экране (месте под Солнцем). При этом фигурируют три размера:
- Располагаемый размер ( available size ) - максимальная область, которую родитель готов первоначально предоставить потомку
- Предпочтительный размер ( desired size ) - размер, который желал бы установить потомок
- Фактический размер ( actual size ) - окончательный размер, который родитель назначает потомку
На размеры элемента могут налагаться ограничения MinWidth, MaxWidth, MinHeight и MaxHeight, внутри которых может выполнять адаптация под содержимое. Свойства Width и Height обычно не задаются, что разрешает автоматический выбор размера, но при явном их задании адаптация под размер отключается. Свойства ActualWidth и ActualHeight становятся определенными только после окончания двухэтапной адаптации и означают фактичекий размер элемента, установленный менеджером размещения.
- Добавьте к решению новый проект WpfApp9 типа WPF Application и назначьте его стартовым
- Заполните файл логики Window1.xaml.cs следующим кодом
Вызов метода Arrange для дочернего элемента подтверждает заключение с ним контракта, а без этого элемент не буден виден на экране (попробуйте закомментировать).
- Заполните файл разметки Window1.xaml следующим кодом XAML
Обратите внимание, что для видимости нашего класса MyPanel в разметочной части мы подключили к ней пространство имен среды исполнения CLR, обозначив его произвольным именем.
- Запустите упражнение - окончательный результат выполнения будет выглядеть примерно так
Дата добавления: 2015-04-15; просмотров: 971;