Опубликован: 05.08.2010 | Уровень: специалист | Доступ: платный
Самостоятельная работа 9:

Основы WPF

Упражнение 8. Панель Grid

В панели UniformGrid все ячейки имеют одинаковый размер. В некоторых случаях этого может быть недостаточно, тогда применяют более развитую панель Grid, у которой соседние строки могут иметь разную высоту, а соседние столбцы - разную ширину. Элемент Grid самый гибкий и универсальный из всех менеджеров размещения. Он восполняет применительно к окнам широко используемую в HTML функциональность элемента Table. Недаром мастер заготовки WPF -приложения первоначально включает в разметку именно элемент Grid.

Размещение в сетке Grid состоит из двух этапов: вначале выполняется определение строк и столбцов, а затем производится задание потомков и распределение их по слотам. Самый простой способ использования Grid, это задать свойства RowDefinitions и ColumnDefinitions, добавить несколько дочерних элементов и с помощью присоединенных к ним свойств Grid.Row и Grid.Column указать, какого потомка в какой слот (заготовленное место, ячейка) поместить. Но существуют и более тонкие настройки Grid, которые мы и рассмотрим в данном упражнении.

Создание заготовки приложения

  • Добавьте к решению новый проект WpfApp8 типа WPF Application и назначьте его стартовым
  • Заполните файл разметки Window1.xaml следующим кодом
<Window x:Class="WpfApp8.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Упражнение 8. Панель Grid" 
    Height="300" Width="300"
    Background="LightGray"
        >
    <TabControl>        
        
        <TabItem Header="Grid 0">
        </TabItem>
        
        <TabItem Header="Grid 1">
        </TabItem>
        
        <TabItem Header="Grid 2">
        </TabItem>
        
        <TabItem Header="Grid 3">
        </TabItem>
        
        <TabItem Header="Grid 4">
        </TabItem>
        
        <TabItem Header="Grid 5">
        </TabItem>
        
        <TabItem Header="Grid 6">
        </TabItem>
        
        <TabItem Header="Grid 7">
        </TabItem>
    </TabControl>
</Window>
  • Запустите приложение


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

Простое применение Grid

  • Заполните вкладку Grid 0 приведенным ниже кодом и запустите приложение


<TabItem Header="Grid 0">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition />
                    <RowDefinition />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition />
                    <ColumnDefinition />
                </Grid.ColumnDefinitions>
                <Button Grid.Row="0" Grid.Column="0" Background="LightPink">Первый</Button>
                <Button Grid.Row="1" Grid.Column="0" Background="Lime">Второй</Button>
                <Button Grid.Row="1" Grid.Column="1" Background="Aquamarine">Третий (длинное содержимое)</Button>
                <Button Grid.Row="0" Grid.Column="1" Background="Yellow">Четвертый</Button>
            </Grid>
        </TabItem>

Две секции <Grid.RowDefinitions> и <Grid.ColumnDefinitions> определяют строки и столбцы сетки. Дескрипторы <RowDefinition /> и <ColumnDefinition/> задают количество строк и столбцов. Здесь они применяются без параметров, поэтому устанавливают равные условия для всех слотов (зарезервированного места) сетки. Далее следуют размещаемые элементы, в качестве которых мы используем разноцветные кнопки. Порядок следования потомков здесь не играет значения, поскольку каждому из них явно указывается закрепленный за ним слот. Если содержимое потомка не умещается в отведенный слот, то по умолчанию оно усекается.

  • Поизменяйте размеры окна, чтобы почувствовать работу панели при данных настройках

Автоматическая подстройка под содержимое слотов

  • Заполните вкладку Grid 1 приведенным ниже кодом и запустите приложение


<TabItem Header="Grid 1">
            <Grid HorizontalAlignment="Center" VerticalAlignment="Center">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="Auto" />
                </Grid.ColumnDefinitions>
                <Button Grid.Row="0" Grid.Column="0" Background="LightPink">Первый</Button>
                <Button Grid.Row="0" Grid.Column="1" Background="Lime">Второй</Button>
                <Button Grid.Row="1" Grid.Column="0" Background="Aquamarine">Третий (длинное содержимое)</Button>
                <Button Grid.Row="1" Grid.Column="1" Background="Yellow">Четвертый</Button>
            </Grid>
        </TabItem>

Дескрипторы <RowDefinition Height="Auto" /> и <ColumnDefinition Width="Auto" /> не только определяют количество строк и столбцов сетки, но и могут устанавливать режимы подстройки под содержимое. Значения "Auto" параметров высоты и ширины как раз это и означают.

Жесткая установка размеров ячеек

  • Заполните вкладку Grid 2 приведенным ниже кодом и запустите приложение


<TabItem Header="Grid 2">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="50" />
                    <RowDefinition Height="*" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="50" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <Button Grid.Row="0" Grid.Column="0" MinWidth="0" Background="LightPink">Первый</Button>
                <Button Grid.Row="0" Grid.Column="1" MinWidth="0" Background="Lime">Второй</Button>
                <Button Grid.Row="1" Grid.Column="0" MinWidth="0" Background="Aquamarine">Третий</Button>
                <Button Grid.Row="1" Grid.Column="1" MinWidth="0" Background="Yellow">Четвертый</Button>
            </Grid>
        </TabItem>

В дескрипторах определения строк и столбцов для рассматриваемого варианта жестко задаются высота первой строки и ширина первого столбца. Установка размера в значение "*" означает, что он нелимитирован и соответствующие строка или столбец займут оставшееся от других свободное место родителя. Параметры MinWidth в определениях потомков являются в данном случае необязательными и указывают минимальную границу изменения размера потомка по ширине.

  • Поизменяйте размеры окна и убедитесь, что жестко заданные размеры первого слота строго выдерживаются сеткой

Задание пропорций

  • Заполните вкладку Grid 3 приведенным ниже кодом и запустите приложение


<TabItem Header="Grid 3">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="2*" />
                    <RowDefinition Height="1*" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="2*" />
                    <ColumnDefinition Width="1*" />
                </Grid.ColumnDefinitions>
                <Button Grid.Row="0" Grid.Column="0" MinWidth="0" Background="LightPink">Первый</Button>
                <Button Grid.Row="0" Grid.Column="1" MinWidth="0" Background="Lime">Второй</Button>
                <Button Grid.Row="1" Grid.Column="0" MinWidth="0" Background="Aquamarine">Третий</Button>
                <Button Grid.Row="1" Grid.Column="1" MinWidth="0" Background="Yellow">Четвертый</Button>
            </Grid>
        </TabItem>

Приведенные в каждой секции строк и столбцов данного кода определения размеров устанавливают пропорции, которые должны поддерживаться между этим строками или столбцами. Для любой из приведенных секций можно было бы задать и другие размеры, например <RowDefinition Height="20*" /> и <RowDefinition Height="10*" />, все равно пропорции останутся прежними ( 2/1 ).

Одинаковая подстройка под наибольшее содержимое

  • Заполните вкладку Grid 4 приведенным ниже кодом и запустите приложение


<TabItem Header="Grid 4">
            <Grid HorizontalAlignment="Center" VerticalAlignment="Stretch">
                <Grid.RowDefinitions>
                    <RowDefinition />
                    <RowDefinition />
                    <RowDefinition />
                    <RowDefinition />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                </Grid.ColumnDefinitions>
                <Button Grid.Row="0" Background="LightPink">Первый</Button>
                <Button Grid.Row="1" Background="Lime">Второй</Button>
                <Button Grid.Row="2" Background="Aquamarine">Третий - самое длинное содержимое</Button>
                <Button Grid.Row="3" Background="Yellow">Четвертый</Button>
            </Grid>
        </TabItem>

Мы определили четыре строки и один столбец и задали автоматическую подстройку под наибольшее содержимое элементов столбца. Сетка подстраивается по высоте под свободное пространство родителя (вкладки), поскольку для нее мы задали VerticalAlignment="Stretch" (он же и по умолчанию), а высоту ячеек не задали.

Алексей Бабушкин
Алексей Бабушкин

При выполнении в лабораторной работе упражнения №1 , а именно при выполнении нижеследующего кода:

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using Microsoft.Xna.Framework.Graphics;

   

namespace Application1

{

    public partial class MainForm : Form

    {

        // Объявим поле графического устройства для видимости в методах

        GraphicsDevice device;

   

        public MainForm()

        {

            InitializeComponent();

   

            // Подпишемся на событие Load формы

            this.Load += new EventHandler(MainForm_Load);

   

            // Попишемся на событие FormClosed формы

            this.FormClosed += new FormClosedEventHandler(MainForm_FormClosed);

        }

   

        void MainForm_FormClosed(object sender, FormClosedEventArgs e)

        {

            //  Удаляем (освобождаем) устройство

            device.Dispose();

            // На всякий случай присваиваем ссылке на устройство значение null

            device = null;       

        }

   

        void MainForm_Load(object sender, EventArgs e)

        {

            // Создаем объект представления для настройки графического устройства

            PresentationParameters presentParams = new PresentationParameters();

            // Настраиваем объект представления через его свойства

            presentParams.IsFullScreen = false; // Включаем оконный режим

            presentParams.BackBufferCount = 1;  // Включаем задний буфер

                                                // для двойной буферизации

            // Переключение переднего и заднего буферов

            // должно осуществляться с максимальной эффективностью

            presentParams.SwapEffect = SwapEffect.Discard;

            // Устанавливаем размеры заднего буфера по клиентской области окна формы

            presentParams.BackBufferWidth = this.ClientSize.Width;

            presentParams.BackBufferHeight = this.ClientSize.Height;

   

            // Создадим графическое устройство с заданными настройками

            device = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, DeviceType.Hardware,

                this.Handle, presentParams);

        }

   

        protected override void OnPaint(PaintEventArgs e)

        {

            device.Clear(Microsoft.Xna.Framework.Graphics.Color.CornflowerBlue);

   

            base.OnPaint(e);

        }

    }

}

Выбрасывается исключение:

Невозможно загрузить файл или сборку "Microsoft.Xna.Framework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=6d5c3888ef60e27d" или один из зависимых от них компонентов. Не удается найти указанный файл.

Делаю все пунктуально. В чем может быть проблема?

Dmitriy Ivanchenko
Dmitriy Ivanchenko
Украина, Кировоград, Виктория-П, 2011
Татьяна Ковалюк
Татьяна Ковалюк
Украина, Киев, Киевский политехнический институт, 1974