Исходные коды программ и игр

Программирование - работа и хобби

Адаптивная компоновка на WPF

Язык программирования C#

Отличие WPF компоновки от других методик

Компоновка интерфейсов приложений WPF в корне отличается от методик размещения визуальных элементов C++ Win32, C++ MFC, C# Windows Forms. В ранних системах распределение элементов интерфейса строилось на абсолютных величинах, отсчитываемых от краёв окна: Left, Top, Right, Bottom. С появлением резиновых контейнеров FlowLayoutPanel TableLayoutPanel в Windows Forms появилась возможность создавать гибкие, Web-подобные интерфейсы. Вероятно, для увеличения возможностей дизайнеров и конкурентная борьба мировых операционных систем побудили разработчиков команды Microsoft к созданию платформы интерфейсов нового поколения Windows Presentation Foundation.

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

Примеры компоновки

К данной статье прилагаются исходники 3-х программ на WPF с различной компоновкой. Приложения созданы на модульной платформе .NET Core. Программа «Языки программирования» имеет наиболее сложный адаптивный интерфейс и пополняемую XML базу данных. Программа презентации имеет интерфейс близкий к Web-фронтенду. И интерфейс калькулятора демонстрирует как можно быстро изготовить макет с множеством одинаковых элементов.

Программа «Языков программирования»

Приложение языки программирования  на <em>WPF</em>Полноценное приложение с адаптивной компоновкой на платформе WPF. Программа представляет собой информационное приложение для изучения языков программирования. Информация, в виде XML базы данных, хранится отдельно в папке приложения.

Для примера в базу данных приложения внесены данные языков: C#, C++, Java, Python, PHP. При необходимости базу можно дополнить данными других языков. Доступ к XML базе осуществляется классическим способом, без привязки данных. Интерфейс приложения показывает текстовые описания, изображения и примеры исходных кодов для наглядности.

Приложение «Языки программирования» имеет компоновку, подстраивающуюся под различные размеры окна. Макет приложения построен на нескольких типах контейнеров, которые вмещают в себя, также, различные виды элементов управления. Интерфейс получился довольно гибкий, и информация приемлемо читается и смотрится в окне с размерами от 600х400 пикселей.

Для удобного восприятия информации шрифты приложения масштабируются в зависимости от размеров окна. Размеры шрифтов привязаны к базовой ширине окна. При изменении ширины соответственно уменьшаются или увеличиваются шрифты заголовков и текста приложения. Основную часть обеспечения адаптивности интерфейса берут на себя умные контейнеры платформы Windows Presentation Foundation. Добавлен лишь небольшой программный код и приложение сформировалось полностью.

Адаптивная компоновка

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

В приложении "Языки программирования" макет интерфейса начинается с панели Grid. Данная панель имеет табличную структуру и позволяет вмещать в себя множество дочерних элементов. Grid наиболее универсальный контейнер, умеет формировать ячейки с адаптивной и фиксированной шириной. Контейнер Grid и его ячейки не имеют свойства Padding и не создают видимых границ, в этом случае его удачно дополняет декоративный компонент Border. В компоновке макета и применён этот удачный симбиоз. В свою очередь Border может вмещать в себя только один элемент. Расширить возможности декоративного компонента можно разместив в нём любой контейнер производный от класса Panel.

Текстовые заголовки интерфейса отображены элементом управления TextBlock. Текстовые блоки отлично подходят для небольшого текста, не более нескольких строк. Для больших объемов текстового содержимого рекомендуется использовать потоковые документы FlowDocument.

В случае, когда визуальный элемент не может отобразится полностью в отведённом ему пространстве, можно обернуть элемент экземпляром класса прокрутки ScrollViewer. При урезании видимой части компонента появляются полосы прокрутки дающие возможность увидеть скрытые области.

Программа презентации

Программа презентации  на WPFИнтерфейс программы презентации, по своей реакции на изменение размера, напоминает HTML каркас Bootstrap. При растягивании окна элементы выстраиваются горизонтально в одну строку, при уменьшении ширины компоненты располагаются, сначала попарно в двух строках, затем складываются в один столбец.

Адаптивность интерфейса достигается с помощью контейнеров WrapPanel. В макете участвуют изображения и текстовые описания обёрнутые во FlowDocument.

Компоновка на WrapPanel

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

StackPanel в данном макете служит для расположения друг над другом смежных элементов: изображения и текстового блока. StackPanel умеет размещать дочерние элементы вертикально или горизонтально. По умолчанию установлено вертикальное размещение.

В заголовке презентации, контейнером служит экземпляр декоративного класса Border. Часто Border применяют в макетах для получения дистанции Padding в контейнерах с отсутствием аналогичного свойства. Все контейнеры и элементы презентации заключены в один корневой контейнер Grid с двумя строками. Один, поскольку класс окна не допускает несколько вложенных компонентов.

Графика и код

Дизайнерская часть в приложениях WPF отделена от программной. Основная графическая часть находится в текстовом файле XAML (язык разметки пользовательских интерфейсов, похожий на XML). Хотя можно всю графику строить и программным способом, XAML позволяет визуально отлаживать макет интерфейса. Visual Studio имеет XAML дизайнер помогающий визуально отлаживать интерфейсы приложений WPF. В комплект Visual Studio также входит дизайнерский инструмент Microsoft Blend для автоматизированного проектирования интерфейсов XAML. Microsoft Blend позволяет визуально создавать и отлаживать анимацию. Это быстрее и удобнее, чем создание анимации в коде.

Интерфейс Калькулятор

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

Данный контейнер представляет собой адаптивную сеточную структуру с ячейками одинакового размера. Контейнер располагает дочерние элементы в порядке их добавления в родительский контейнер. Если значения для строк и столбцов не указаны, UniformGrid создаст квадратный макет на основе общего количества видимых элементов, где количество строк будет равно количеству столбцов. Интерфейс калькулятора создан полностью на XAML, без применения программного кода.

XAML калькулятора

<Window x:Class="WpfCalculator.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfCalculator"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="350">
    <Window.Resources>
        <Style TargetType="Button">
            <Setter Property="FontSize" Value="26"/>
            <Setter Property="FontWeight" Value="Normal"/>
            <Setter Property="Margin" Value="2,2,2,2" />
            <Setter Property="BorderThickness" Value="1,1,3,3"></Setter>
            <EventSetter Event="Click" Handler="Button_Click" />
        </Style>
    </Window.Resources>

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="2*"/>
            <RowDefinition Height="6*"/>
        </Grid.RowDefinitions>
        <Border x:Name="Scoreboard" BorderThickness="3,3,1,1" BorderBrush="#FFAAA6A6" 
              HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="#FFE2F3EC" 
                  Padding="5,0,5,0" Margin="2,3,2,2">
            <TextBlock x:Name="Digits" TextAlignment="Right" Text="2345,678" FontSize="40"  
                  UseLayoutRounding="False" VerticalAlignment="Bottom" Grid.IsSharedSizeScope="True" 
                     FontWeight="Normal" ScrollViewer.VerticalScrollBarVisibility="Disabled" 
                        Padding="0,0,0,5" HorizontalAlignment="Stretch" />
        </Border>

        <UniformGrid Grid.Row="1"  Rows="6" Columns="4"  Margin="0,0,0,1">

            <!-- Функциональные клавиши -->
            <Button Background="#FFDDDDDD" Content="%"/>
            <Button Background="#FFDDDDDD" Content="CE" />
            <Button Background="#FFDDDDDD" Content="C" />
            <Button Background="#FFDDDDDD" Content="⇐" />
            <Button Background="#FFDDDDDD" Content="1/x" />
            <Button Background="#FFDDDDDD" Content="x²" />
            <Button Background="#FFDDDDDD" Content="√x" />
            <Button Background="#FFDDDDDD" Content="÷" />
            <!-- /Функциональные клавиши -->

            <!-- Номерные клавиши -->
            <Button Content="7" Background="White" />
            <Button Content="8" Background="White" />
            <Button Content="9" Background="White" />
            <!-- /Номерные клавиши -->

            <!-- Функциональные клавиши -->
            <Button Content="x" Background="#FFDDDDDD" />
            <!-- /Функциональные клавиши -->

            <!-- Номерные клавиши -->
            <Button Content="4" Background="White" />
            <Button Content="5" Background="White" HorizontalAlignment="Stretch" />
            <Button Content="6" Background="White" />
            <!-- /Номерные клавиши -->

            <!-- Функциональные клавиши -->
            <Button Content="-" Background="#FFDDDDDD" />
            <!-- /Функциональные клавиши -->

            <!-- Номерные клавиши -->
            <Button Content="1" Background="White" />
            <Button Content="2" Background="White" />
            <Button Content="3" Background="White" />
            <!-- /Номерные клавиши -->

            <!-- Функциональные клавиши -->
            <Button Content="+" Background="#FFDDDDDD" />
            <!-- /Функциональные клавиши -->

            <!-- Номерные клавиши -->
            <Button Content="+/-" Background="White" />
            <Button Content="0" Background="White" />
            <Button Content="," Background="White" />
            <!-- /Номерные клавиши -->

            <!-- Функциональные клавиши -->
            <Button Content="=" Background="#FFDDDDDD" />
            <!-- /Функциональные клавиши -->

        </UniformGrid>
    </Grid>
</Window>

Общие стили для всех кнопок

В качестве кнопок калькулятора выступают одноимённые элементы Button. Графические возможности WPF предоставляют возможность создать любую цветовую гамму кнопкам. В приложении кнопки мягких серых оттенков. Для стандартизации поведения и внешнего вида кнопок в программе использованы стили.

Стили в WPF играют ту же роль что и CSS в HTML разметке и даже больше: дают возможность совместного использование свойств, ресурсов, обработчиков событий, триггеров. Изменяя параметры стилей, мы можем воздействовать одновременно на большое количество экземпляров классов WPF. Стили представлены классом Style производным от DispatcherObject. В калькуляторе стили определены на уровне окна, для всех экземпляров класса Button.

Общие стили для всех элементов Button калькулятора:
<Window.Resources>
    <Style TargetType="Button">
        <Setter Property="FontSize" Value="26"/>
        <Setter Property="FontWeight" Value="Normal"/>
        <Setter Property="Margin" Value="2,2,2,2" />
        <Setter Property="BorderThickness" Value="1,1,3,3"></Setter>
        <EventSetter Event="Click" Handler="Button_Click" />
    </Style>
</Window.Resources>

Архив исходника включает все описанные программы с выполняемыми файлами .exe. Инструмент программирования MS Visual Studio 2019, кроссплатформа .NET Core 3.1.

Файл: wpf-arrangement-vs2019.zip
Размер: 2692 Кбайт
Загрузки: 47