Обучение
Модуль
Настройка макета на страницах .NET MAUI XAML - Training
Создание согласованного пользовательского интерфейса на различных устройствах с помощью StackLayout и Grid.
Этот браузер больше не поддерживается.
Выполните обновление до Microsoft Edge, чтобы воспользоваться новейшими функциями, обновлениями для системы безопасности и технической поддержкой.
Панель — это объект, который предоставляет поведение макета для дочерних элементов, содержащихся в нем, когда выполняется система макета расширяемого языка разметки приложений (XAML) и отрисовывается пользовательский интерфейс приложения.
Важные API: Панель, УпорядочитьOverride, MeasureOverride
Пользовательские панели для макета XAML можно определить, наследив пользовательский класс из класса Panel. Вы предоставляете поведение для панели, переопределяя MeasureOverride и ArrangeOverride, предоставляя логику, которая измеряет и упорядочивает дочерние элементы.
Чтобы определить пользовательский класс панели, можно либо наследовать из класса Panel напрямую, либо получить от одного из практических классов панели, которые не запечатаны, например Grid или StackPanel. Проще наследоваться от панели, так как ее можно обойти с существующей логикой макета панели, которая уже имеет поведение макета. Кроме того, панель с поведением может иметь существующие свойства, которые не относятся к функциям макета панели.
На панели настраиваемая панель наследует следующие API:
Здесь основное внимание уделяется описанию концепций макета XAML, поэтому вы можете рассмотреть все возможности того, как пользовательская панель может и должна вести себя в макете. Если вы хотите перейти вправо и увидеть пример реализации настраиваемой панели, см . пример настраиваемой панели BoxPanel.
Свойство Children относится к пользовательской панели, так как все классы, производные от Панели, используют свойство Children в качестве места для хранения содержащихся дочерних элементов в коллекции. Дочерние элементы называются свойством содержимого XAML для класса Panel , и все классы, производные от панели , могут наследовать поведение свойства содержимого XAML. Если свойство присваивается свойству содержимого XAML, это означает, что разметка XAML может опустить элемент свойства при указании этого свойства в разметке, а значения задаются как непосредственные дочерние элементы разметки (содержимое). Например, если вы наследуете класс CustomPanel из Панели , который не определяет новое поведение, вы по-прежнему можете использовать эту разметку:
<local:CustomPanel>
<Button Name="button1"/>
<Button Name="button2"/>
</local:CustomPanel>
Когда средство синтаксического анализа XAML считывает эту разметку, дочерние элементы, как известно, являются свойством содержимого XAML для всех производных типов Панели, поэтому средство синтаксического анализа добавит два элемента Button в значение UIElementCollection свойства Children. Свойство содержимого XAML упрощает упрощенную связь родительского-дочернего элемента в разметке XAML для определения пользовательского интерфейса. Дополнительные сведения о свойствах содержимого XAML и заполнении свойств коллекции при анализе XAML см. в руководстве по синтаксису XAML.
Тип коллекции, поддерживающий значение свойства Children, является класс UIElementCollection. UIElementCollection — это строго типизированная коллекция, которая использует UIElement в качестве его принудительного типа элемента. UIElement — это базовый тип, наследуемый сотнями практических типов элементов пользовательского интерфейса, поэтому применение типов здесь намеренно свободно. Но он применяется, что у вас не может быть Кисть в качестве прямого дочернего элемента панели, и обычно это означает, что только элементы, которые, как ожидается, будут отображаться в пользовательском интерфейсе и участвовать в макете будут найдены как дочерние элементы на панели.
Как правило, пользовательская панель принимает любой дочерний элемент UIElement по определению XAML, просто используя характеристики свойства Children as-is. В качестве расширенного сценария можно поддерживать дополнительную проверку типов дочерних элементов при переопределении коллекции в макете.
Помимо циклического прохождения коллекции "Дочерние" в переопределениях, логика панели также может влиять на Children.Count
. У вас может быть логика, которая выделяет пространство по крайней мере частично на основе количества элементов, а не требуемых размеров и других характеристик отдельных элементов.
Базовая модель для методов переопределения макета (MeasureOverride и ArrangeOverride) заключается в том, что они должны выполнять итерацию всех дочерних элементов и вызывать конкретный метод макета каждого дочернего элемента. Первый цикл макета начинается, когда система макета XAML задает визуальный элемент для корневого окна. Так как каждый родительский элемент вызывает макет в дочерних элементах, он распространяет вызов методов макета к каждому возможному элементу пользовательского интерфейса, который должен быть частью макета. В макете XAML существует два этапа: мера, а затем упорядочение.
Вы не получаете встроенного метода макета для MeasureOverride и ArrangeOverride из базового класса Panel. Элементы в дочерних элементах не будут автоматически отображаться в виде части визуального дерева XAML. Это позволяет сделать элементы известными для процесса макета, вызывая методы макета для каждого из элементов, которые вы найдете в дочерних элементах через проход макета в реализации MeasureOverride и ArrangeOverride.
Нет никаких причин вызывать базовые реализации в переопределениях макета, если у вас нет собственного наследования. Собственные методы для поведения макета (если они существуют) выполняются независимо, и не вызывая базовую реализацию из переопределения, не препятствуют возникновению собственного поведения.
Во время прохождения мер логика макета запрашивает каждый дочерний элемент для требуемого размера, вызывая метод Measure для этого дочернего элемента. Вызов метода Measure устанавливает значение свойства DesiredSize. Возвращаемое значение MeasureOverride — это требуемый размер самой панели.
Во время прохождения упорядочивания позиции и размеры дочерних элементов определяются в пространстве x-y, а композиция макета подготовлена для отрисовки. Код должен вызывать "Упорядочить" для каждого дочернего элемента в Дочерних элементах, чтобы система макета обнаружила, что элемент принадлежит в макете. Вызов Упорядочивания является предшественником композиции и отрисовки; он сообщает системе макета, где этот элемент идет, когда композиция отправляется для отрисовки.
Многие свойства и значения способствуют работе логики макета во время выполнения. Способ думать о процессе макета заключается в том, что элементы без дочерних элементов (как правило, наиболее глубоко вложенный элемент в пользовательском интерфейсе) — это те, которые могут сначала завершить измерения. У них нет зависимостей от дочерних элементов, влияющих на их требуемый размер. Они могут иметь свои собственные нужные размеры, и это предложения по размеру до тех пор, пока макет на самом деле не будет установлен. Затем передача меры продолжает идти вверх по визуальному дереву, пока корневой элемент не будет иметь свои измерения и все измерения можно завершить.
Макет кандидата должен соответствовать текущему окну приложения или другим частям пользовательского интерфейса. Панели часто являются местом, где определяется логика вырезки. Логика панели может определить размер, доступный в реализации MeasureOverride , и может потребоваться отправить ограничения размера на дочерние элементы и разделить пространство между детьми, чтобы все вместилось как можно лучше. В идеале результат макета — это то, что использует различные свойства всех частей макета, но по-прежнему помещается в окно приложения. Для этого требуется хорошая реализация логики макета панелей, а также разумный дизайн пользовательского интерфейса в части любого кода приложения, создающего пользовательский интерфейс с помощью этой панели. Дизайн панели не будет выглядеть хорошо, если общая конструкция пользовательского интерфейса включает в себя больше дочерних элементов, чем может быть включено в приложение.
Большая часть того, что делает работу системы макета, заключается в том, что любой элемент, основанный на FrameworkElement , уже имеет некоторое собственное поведение при действии в качестве дочернего элемента в контейнере. Например, существует несколько API FrameworkElement, которые информируют о поведении макета или необходимы для работы макета. Например:
Метод MeasureOverride имеет возвращаемое значение, используемое системой макета в качестве запуска DesiredSize для самой панели, когда метод Measure вызывается на панели его родительским элементом в макете. Выбор логики в методе так же важен, как и то, что он возвращает, и логика часто влияет на возвращаемое значение.
Все реализации MeasureOverride должны выполнять циклы по дочерним элементам и вызывать метод Measure для каждого дочернего элемента. Вызов метода Measure устанавливает значение свойства DesiredSize. Это может сообщить, сколько пространства требуется самой панели, а также как это пространство делится между элементами или размером для определенного дочернего элемента.
Ниже приведен очень базовый скелет метода MeasureOverride:
protected override Size MeasureOverride(Size availableSize)
{
Size returnSize; //TODO might return availableSize, might do something else
//loop through each Child, call Measure on each
foreach (UIElement child in Children)
{
child.Measure(new Size()); // TODO determine how much space the panel allots for this child, that's what you pass to Measure
Size childDesiredSize = child.DesiredSize; //TODO determine how the returned Size is influenced by each child's DesiredSize
//TODO, logic if passed-in Size and net DesiredSize are different, does that matter?
}
return returnSize;
}
Элементы часто имеют естественный размер к тому времени, когда они готовы к макету. После прохождения мер параметр DesiredSize может указать, что естественный размер, если доступный размер, который вы передали для measure, был меньше. Если естественный размер превышает доступный размер, который вы передали для Measure, параметр DesiredSize ограничен доступнойSize. Это то, как выполняется внутренняя реализация Measure, и переопределения макета должны учитывать это поведение.
Некоторые элементы не имеют естественного размера, так как они имеют автоматические значения для высоты и ширины. Эти элементы используют полную доступностьSize, так как это то, что представляет автоматическое значение: размер элемента до максимального доступного размера, который родитель немедленного макета взаимодействует с помощью вызова Measure с availableSize. На практике всегда есть некоторые измерения, которые пользовательский интерфейс имеет размер (даже если это окно верхнего уровня).) В конечном итоге передача меры разрешает все значения auto в родительские ограничения, а все элементы автозначных значений получают реальные измерения (которые можно получить, проверив ActualWidth и ActualHeight после завершения макета).
Это законно передать размер в Меру, которая имеет по крайней мере одно бесконечное измерение, чтобы указать, что панель может попытаться размерить себя, чтобы соответствовать измерениям его содержимого. Каждый дочерний элемент, измеряемый, задает значение DesiredSize с помощью естественного размера. Затем во время прохождения упорядочивания панель обычно упорядочивает этот размер.
Текстовые элементы, такие как TextBlock, имеют вычисляемый код ActualWidth и ActualHeight на основе их текстовых строк и текстовых свойств, даже если значение высоты или ширины не задано, и эти измерения должны соблюдаться логикой панели. Вырезка текста является особенно плохим интерфейсом.
Даже если ваша реализация не использует требуемые измерения размера, рекомендуется вызвать метод Measure для каждого дочернего элемента, так как вызываются внутренние и собственные поведения, которые активируются методом Measure. Для участия элемента в макете каждый дочерний элемент должен иметь метод Measure, вызываемый им во время прохождения меры, и метод Упорядочения, вызываемый им во время прохождения упорядочения. Вызов этих методов задает внутренние флаги объекта и заполняет значения (например , свойство DesiredSize ), необходимые для логики макета системы при создании визуального дерева и отрисовке пользовательского интерфейса.
Возвращаемое значение MeasureOverride основано на логике панели, интерпретирующей Метод DesiredSize или другие рекомендации по размеру для каждого дочернего элемента в Дочерних элементах при вызове меры. Что делать с значениями DesiredSize от дочерних элементов и как возвращаемое значение MeasureOverride должно использовать их до интерпретации собственной логики. Обычно значения не добавляются без изменений, так как входные данные MeasureOverride часто являются фиксированным доступным размером, предлагаемым родительским элементом панели. При превышении этого размера сама панель может быть обрезана. Обычно вы сравниваете общий размер дочерних элементов с доступным размером панели и при необходимости вносите корректировки.
Метод ArrangeOverride имеет возвращаемое значение Size, используемое системой макета при отрисовке самой панели, когда метод "Упорядочить" вызывается на панели его родительским элементом в макете. Как правило, входной финалSize и возвращаемый размер Объекта ArrangeOverride совпадают. Если они нет, это означает, что панель пытается сделать себя другим участником утверждения макета доступным. Окончательный размер был основан на том, что ранее был выполнен проход меры через код панели, поэтому возврат другого размера не является типичным: это означает, что вы намеренно игнорируете логику мер.
Не возвращайте размер с компонентом Бесконечности. При попытке использовать такой размер создается исключение из внутреннего макета.
Все реализации ArrangeOverride должны выполнять циклы по дочерним элементам и вызывать метод Arrange для каждого дочернего элемента. Как и Measure, у упорядочивания нет возвращаемого значения. В отличие от Measure, вычисляемое свойство не получается в результате (однако элемент, заданный в вопросе, обычно вызывает событие LayoutUpdated).
Вот очень базовый скелет метода ArrangeOverride:
protected override Size ArrangeOverride(Size finalSize)
{
//loop through each Child, call Arrange on each
foreach (UIElement child in Children)
{
Point anchorPoint = new Point(); //TODO more logic for topleft corner placement in your panel
// for this child, and based on finalSize or other internal state of your panel
child.Arrange(new Rect(anchorPoint, child.DesiredSize)); //OR, set a different Size
}
return finalSize; //OR, return a different Size, but that's rare
}
Передача макета может произойти без прохождения меры. Однако это происходит только в том случае, если система макета не изменила свойства, которые повлияли бы на предыдущие измерения. Например, если выравнивание изменяется, не нужно повторно измерять этот элемент, так как его DesiredSize не изменится при изменении выбора выравнивания. С другой стороны, если ActualHeight изменяет любой элемент в макете, требуется новый проход меры. Система макета автоматически обнаруживает изменения истинной меры и снова вызывает передачу меры, а затем запускает другой проход упорядочения.
Входные данные для Упорядочивания принимают значение Rect. Наиболее распространенным способом создания этого прямоугольника является использование конструктора, имеющего входные данные точки и входные данные размера. Точка — это точка, в которой должен размещаться верхний левый угол ограничивающего прямоугольника элемента. Размер — это измерения, используемые для отрисовки этого конкретного элемента. Для этого элемента часто используется DesiredSize, так как установка DesiredSize для всех элементов, участвующих в макете, была целью прохождения меры макета. (Передача мер определяет все размеры элементов в итеративном режиме, чтобы система макета могли оптимизировать размещение элементов после того, как он перейдет к проходу упорядочения.)
Как правило, реализация ArrangeOverride зависит от логики, с помощью которой панель определяет компонент Point, определяющий порядок размещения каждого дочернего элемента. Абсолютная панель размещения, например Canvas, использует явные сведения о размещении, полученные из каждого элемента через Canvas.Left и Canvas.Top значения. Панель разделения пространства, например Сетка , будет иметь математические операции, разделяющие доступное пространство на ячейки, и каждая ячейка будет иметь значение x-y, для которого его содержимое должно быть помещено и упорядочено. Адаптивная панель, например StackPanel , может расширяться, чтобы соответствовать содержимому в его измерении ориентации.
Существуют все еще дополнительные влияния на элементы в макете, помимо того, что вы напрямую управляете и передаете в Упорядочивание. Это происходит из внутренней реализации производного объекта Arrange , который является общим для всех производных типов FrameworkElement и дополнен некоторыми другими типами, такими как текстовые элементы. Например, элементы могут иметь поле и выравнивание, а некоторые могут иметь заполнение. Эти свойства часто взаимодействуют. Дополнительные сведения см. в разделе "Выравнивание", " Поля" и "Заполнение".
Избегайте размещения функциональных возможностей в настраиваемую панель, которая вместо этого должна быть создана как пользовательский элемент управления. Роль панели заключается в том, чтобы представить содержимое дочернего элемента, существующее в нем, как функцию макета, которая происходит автоматически. Панель может добавлять украшения в содержимое (аналогично тому, как Border добавляет границу вокруг элемента, который он представляет), или выполнять другие корректировки, связанные с макетом, например заполнение. Но это примерно так далеко, как вы должны идти при расширении выходных данных визуального дерева за пределами отчетов и использования информации от детей.
Если у пользователя есть какое-либо взаимодействие, необходимо написать пользовательский элемент управления, а не панель. Например, панель не должна добавлять окна просмотра прокрутки в содержимое, даже если цель заключается в предотвращении вырезки, так как полосы прокрутки, пальцы и т. д. являются интерактивными частями управления. (Содержимое может иметь полосы прокрутки в конце концов, но вы должны оставить это до логики дочернего элемента. Не заставляйте его добавлять прокрутку как операцию макета.) Вы можете создать элемент управления, а также написать пользовательскую панель, которая играет важную роль в визуальном дереве этого элемента управления, когда речь идет о представлении содержимого в этом элементе управления. Но элемент управления и панель должны быть отдельными объектами кода.
Одна из причин, по которой важно различие между элементом управления и панелью, обусловлена модель автоматизации пользовательского интерфейса и специальными возможностями Майкрософт. Панели обеспечивают поведение визуального макета, а не логическое поведение. Визуальное представление элемента пользовательского интерфейса не является аспектом пользовательского интерфейса, который обычно важен для сценариев специальных возможностей. Специальные возможности предназначены для предоставления частей приложения, которые логически важны для понимания пользовательского интерфейса. При необходимости элементы управления должны предоставлять возможности взаимодействия инфраструктуре модель автоматизации пользовательского интерфейса. Дополнительные сведения см. в разделе "Пользовательские одноранговые узлы автоматизации".
Существуют некоторые другие API- интерфейсы, которые являются частью системы макета, но не объявляются панелью. Их можно использовать в реализации панели или в пользовательском элементе управления, использующего панели.
Справочные материалы
Основные понятия
Отзыв о Windows developer
Windows developer — это проект с открытым исходным кодом. Выберите ссылку, чтобы оставить отзыв:
Обучение
Модуль
Настройка макета на страницах .NET MAUI XAML - Training
Создание согласованного пользовательского интерфейса на различных устройствах с помощью StackLayout и Grid.
Документация
Вы можете определить подключенные макеты, которые следует использовать с контейнерами, такими как элемент управления ItemsRepeater.
Панели макета для приложений Windows - Windows apps
Узнайте, как использовать встроенные панели макета XAML, такие как RelativePanel, StackPanel, Grid и Canvas, для упорядочения и группирования элементов пользовательского интерфейса в приложении.
BoxPanel, пример настраиваемой панели (приложения Для Windows) - Windows apps
Узнайте, как писать код для пользовательского класса Panel, реализовывать методы ArrangeOverride и MeasureOverride и использовать свойство Children.