Компоновка

40

Половина всех усилий при проектировании пользовательского интерфейса уходит на организацию содержимого, чтобы оно было привлекательным, практичным и гибким. Но по-настоящему сложной задачей является адаптация компоновки элементов интерфейса к различным размерам окна.

В WPF компоновка формируется с использованием разнообразных контейнеров. Каждый контейнер обладает собственной логикой компоновки — некоторые укладывают элементы в стопку, другие распределяют их по ячейкам сетки и т.д. Если вы программировали с помощью Windows Forms, то будете удивлены, что компоновку на основе координат в WPF использовать не рекомендуется. Вместо этого упор делается на создание более гибких компоновок, которые могут адаптироваться к изменяющемуся содержимому, разным языкам и широкому разнообразию размеров окон. Для большинства разработчиков переход на технологию WPF с ее новой системой компоновки становится большим сюрпризом — и первой реальной сложностью.

Понятие компоновки в WPF

Модель компоновки WPF отражает существенные изменения подхода разработчиков к проектированию пользовательских интерфейсов Windows. Чтобы понять новую модель компоновки WPF, стоит посмотреть на то, что ей предшествовало.

В .NET 1.0 технология Windows Forms предоставляла весьма примитивную систему компоновки. Элементы управления были фиксированы на месте по жестко закодированным координатам. Единственными удобствами были привязка (anchoring) и стыковка (docking) — два средства, которые позволяли элементам управления перемещаться и изменять свои размеры вместе с их контейнером. Привязка и стыковка были незаменимы для создания простых окон изменяемого размера, например, с привязкой кнопок ОК и Cancel (Отмена) к нижнему правому углу окна, либо когда нужно было заставить элемент TreeView разворачиваться для заполнения всей формы.

Однако они не могли справиться с более сложными задачами компоновки. Например, привязка и стыковка не позволяли организовать пропорциональное изменение размеров двухпанельных окон (с равномерным разделением дополнительного пространства между двумя областями). Они также не слишком помогали в случае высокодинамичного содержимого, например, когда нужно было дать возможность метке расширяться, чтобы вместить больше текста, что приводило к перекрытию соседних элементов управления.

В .NET 2.0 пробел в Windows Forms был восполнен, благодаря двум новым контейнерам компоновки: FlowLayoutPanel и TableLayoutPanel. С использованием этих элементов управления можно создавать более изощренные интерфейсы в стиле веб-приложений. Оба контейнера компоновки позволяли содержащимся в них элементам управления увеличиваться, расталкивая соседние элементы. Это облегчило задачу создания динамического содержимого, создания модульных интерфейсов и локализации приложений. Однако панели компоновки выглядели дополнением к основной системе компоновки Windows Forms, использовавшей фиксированные координаты. Панели компоновки были элегантным решением, но все-таки несколько чужеродным.

В WPF появилась новая система компоновки, большое влияние на которую оказала разработка с помощью Windows Forms. Эта система возвращается к модели .NET 2.0 (координатная компоновка с необязательными потоковыми панелями компоновки), сделав потоковую (flow-based) компоновку стандартной и предложив лишь рудиментарную поддержку координатной компоновки. Преимущества подобного сдвига огромны. Разработчики могут теперь создавать независимые от разрешения и от размеров интерфейсы, которые масштабируются на разных мониторах, подгоняют себя при изменении содержимого и легко поддерживают перевод на другие языки. Однако прежде чем вы воспользуетесь преимуществом этих изменений, следует перестроить образ мышления относительно компоновки.

Философия компоновки WPF

Реальное приложение WPF неизбежно содержит изрядное количество элементов пользовательского интерфейса (элементов ввода, графического содержимого, систем меню, строк состояния и т.п.), которые должны быть хорошо организованы внутри содержащего их окна. Кроме того, виджеты пользовательского интерфейса должны вести себя адекватно в случае изменения конечным пользователем размеров всего окна или его части (как в случае окна с разделителем). Для гарантирования того, что элементы управления WPF сохранят свое положение в принимающем окне, предусмотрено значительное количество типов панелей.

При объявлении элемента управления непосредственно внутри окна, не имеющего панелей, он размещается в центре окна. Рассмотрим следующее простое объявление окна, содержащего единственный элемент типа Button. Независимо от того, как вы будете изменять размеры окна, виджет пользовательского интерфейса всегда окажется на равном удалении от всех четырех границ клиентской области:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Button Height="100" Width="120">OK</Button>
</Window>
Единственный элемент компоновки

Окно WPF может содержать только один элемент. Чтобы разместить более одного элемента и создать практичный пользовательский интерфейс, нужно поместить в окно контейнер и добавлять элементы в этот контейнер. Это ограничение обусловлено тем фактом, что класс Window унаследован от ContentControl.

В WPF компоновка определяется используемым контейнером. Хотя есть несколько контейнеров, среди которых можно выбирать, "идеальное" окно WPF следует описанным ниже ключевым принципам:

Хотя из этих правил существуют исключения, они отражают общие цели проектирования WPF. Другими словами, если вы последуете этим руководствам при построении WPF-приложения, то получите лучший и более гибкий пользовательский интерфейс. Если же вы нарушаете эти правила, то получите пользовательский интерфейс, который не очень хорошо подходит для WPF и его будет значительно сложнее сопровождать.

Пройди тесты
Лучший чат для C# программистов