Опубликован: 05.08.2010 | Доступ: свободный | Студентов: 2008 / 45 | Оценка: 4.50 / 4.40 | Длительность: 60:26:00
Самостоятельная работа 9:

Основы WPF

Упражнение 5. Менеджер размещения Canvas

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

  1. Canvas
  2. StackPanel
  3. DockPanel
  4. UniformGrid
  5. Grid

Панели обеспечивают типичные способы размещения дочерних элементов и в большинстве случаев этого бывает достаточно. Все панели наследуют от абстрактного класса Panel, имеющего, в свою очередь, в качестве базового класс System.Windows.FrameworkElement. Наиболее развитым менеджером размещения является панель Grid. Сами панели являются невидимыми, если явно не задать их фон, а их присутствие обнаруживается только по влиянию на дочерние элементы.

  • Добавьте к решению новый проект WpfApp5 и назначьте его стартовым

  • Заполните файл разметки следующим кодом
<Window x:Class="WpfApp5.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Менеджер размещения Canvas" Height="300" Width="300" 
    Background="LightGray">
    <TabControl>
        <TabItem Header="Canvas 1">
            <Canvas Width="200" Height="100" Background="Aqua">
                <Button Canvas.Left="2" Canvas.Top="2">Left, Top</Button>
                <Button Canvas.Right="2" Canvas.Top="2">Right, Top</Button>
                <Button Canvas.Left="2" Canvas.Bottom="2">Left, Bottom</Button>
                <Button Canvas.Right="2" Canvas.Bottom="2">Right, Bottom</Button>
            </Canvas>
        </TabItem>
        <TabItem Header="Canvas 2">
            <Canvas HorizontalAlignment="Center" VerticalAlignment="Center" Background="Aqua">
                <Button Canvas.Left="2" Canvas.Top="2">Left, Top</Button>
                <Button Canvas.Right="2" Canvas.Top="2">Right, Top</Button>
                <Button Canvas.Left="2" Canvas.Bottom="2">Left, Bottom</Button>
                <Button Canvas.Right="2" Canvas.Bottom="2">Right, Bottom</Button>
            </Canvas>
        </TabItem>
        <TabItem Header="Canvas 3">
            <StackPanel>
                <Button>Button 1</Button>
                <Button>Button 2</Button>
                <Canvas HorizontalAlignment="Center" Background="Aqua">
                    <Button Canvas.Left="-21" Canvas.Top="8">Canvas</Button>
                </Canvas>
            </StackPanel>
        </TabItem>
    </TabControl>
</Window>

В первой вкладке ширина менеджера размещения задана явно, для видимости панели задан ее фон. Привязка к соответствующим углам панели и дочерних элементов осуществляется через дополнительные присоединенные свойства ( присоединенные атрибуты ) Canvas.Left, Canvas.Right, Canvas.Top и Canvas.Bottom. Достаточно только пары свойств привязки, а остальные избыточные свойства привязки игнорируются.

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


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


На третьей вкладке панель StackPanel организует вертикальную стопку из трех элементов, последним из которых является точечная панель Canvas, позиционированная относительно центра с помощью ее свойства HorizontalAlignment. Дочерняя кнопка панели Canvas привязывается за угол со смещением, включая отрицательное смещение по оси x.


Упражнение 6. Менеджеры размещения StackPanel и DockPanel

StackPanel размещает своих потомков построчно, по умолчанию вертикальной стопкой. Свойство Orientation позволяет располагать стопку горизонтально или вертикально. По умолчанию StackPanel занимает всю клиентскую область родителя. Каждому дочернему элементу StackPanel выделяет слот (жизненное пространство), а свой предпочтительный размер вычисляет на основе максимальных размеров своих потомков.

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

  • Добавьте к решению новый проект WpfApp6 и назначьте его стартовым

  • Добавьте к проекту следующую разметку
<Window x:Class="WpfApp6.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="StackPanel, DockPanel" Height="300" Width="300"
    Background="LightGray"
        >
    <TabControl>
        <TabItem Header="StackPanel">
            <Border BorderBrush="Red" BorderThickness="2"
            HorizontalAlignment="Center" VerticalAlignment="Center">
                <StackPanel Orientation="Vertical">
                    <StackPanel Orientation="Horizontal" Margin="5" Background="Aqua">
                        <Button Margin="2">One</Button>
                        <Button Margin="2">Two</Button>
                        <Button Margin="2">Three</Button>
                    </StackPanel>
                    <StackPanel Orientation="Vertical" Margin="5" Background="Yellow">
                        <Button Margin="2">One</Button>
                        <Button Margin="2">Two</Button>
                        <Button Margin="2">Three</Button>
                    </StackPanel>
                    <StackPanel Orientation="Horizontal" Margin="5" Width="100" Background="White">
                        <TextBlock FontSize="18pt" TextWrapping="Wrap">
                            Этот текст не переносится, потому что погружен в StackPanel
                        </TextBlock>
                    </StackPanel>
                </StackPanel>
            </Border>
        </TabItem>
            
        <!--Имитация пространства Windows Explorer с помощью DockPanel-->
        <TabItem Header="DockPanel 1">
            <DockPanel>
                <Button DockPanel.Dock="Top">Menu Area (Dock=Top)</Button>
                <Button DockPanel.Dock="Top">ToolBar Area (Dock=Top)</Button>
                <Button DockPanel.Dock="Left">Folders (Dock=Left)</Button>
                <Button>
                    <TextBlock TextWrapping="Wrap" Padding="5pt">
                        Content (Fills remaining space because LastChildFill="True" - 
                        последний добавленный элемент заполняет остающееся место, 
                        потому что LastChildFill="True" по умолчанию). 
                        Этот текст переносится, потому что погружен в DockPanel
                    </TextBlock>
                </Button>
            </DockPanel>
        </TabItem>
        <TabItem Header="DockPanel 2">
            <DockPanel LastChildFill="True">
                <Button DockPanel.Dock="Top">Menu Area (Dock=Top)</Button>
                <Button DockPanel.Dock="Left">Folders (Dock=Left)</Button>
                <Button DockPanel.Dock="Top">ToolBar Area (Dock=Top)</Button>
                <Button>
                    <TextBlock TextWrapping="Wrap" FontSize="10pt" Padding="5pt">
                        Content (Fills remaining space because LastChildFill="True" - 
                        последний добавленный элемент заполняет остающееся место, 
                        потому что LastChildFill="True"). Этот текст переносится, 
                        потому что погружен в DockPanel
                    </TextBlock>
                </Button>
            </DockPanel>
        </TabItem>
    </TabControl>
</Window>

На первой вкладке рисуется рамка заданной ширины и цвета, в которую погружается StackPanel с вертикальной ориентацией выравнивания. В нее вкладываются еще три панели с разной ориентацией выравнивания элементов и заданным фоном. В последней панели содержится текстовый блок, который не переносит строку, хотя задано свойство TextWrapping="Wrap". Функциональность переноса в текстовом блоке возможна только тогда, когда он погружен в панель DockPanel.


Следующие две вкладки демонстрируют работу менеджера DockPanel. Структура размещения определяется порядком добавления элементов в панель. Свойство LastChildFill позволяет последнему потомку занять все свободное пространство. Для дочерних элементов DockPanel действует присоединенное свойство, которое указывает, к какой стороне свободного места должен быть пристыкован очередной элемент.

DockPanel наиболее употребителен из всех менеджеров размещения. По умолчанию DockPanel не позволяет пользователю перетаскивать границы между областями. Для этого используется GridSplitter, тесно связанный с менеджером Grid и мы его рассмотрим ниже (даже будет контрольное задание!).

В упражнении в качестве размещаемых элементов используются кнопки, которые имитируют структуру Windows Explorer



Обратите внимание на работу менеджеров при изменении размеров окна.

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

При выполнении в лабораторной работе упражнения №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" или один из зависимых от них компонентов. Не удается найти указанный файл.

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