При загрузке данных из БД возникает исключение InvalidOperationException с сообщением: Элемент коллекции должен быть пустым перед использованием ItemsSource. Знаю, что для заполнения DataGrid можно использовать коллекции Items или ItemsSource, но одновременно их использовать нельзя: если задано значение для свойства ItemsSource и в коде C# добавляется элемент в Items, возникает исключение. |
Основы технологии WPF
Компоновка
При проектировании пользовательского интерфейса приложения необходимо сформировать в окне или странице требуемые элементы управления и задать нужные свойства, т.е. провести организацию содержимого. Этот процесс называется компоновкой.
В WPF компоновка осуществляется с использованием различных контейнеров. Каждый контейнер обладает своей собственной логикой компоновки – некоторые укладывают элементы последовательно в строки, другие организуют их в сетку невидимых ячеек
Окно и страница в WPF может содержать только один элемент - контейнер. В контейнер можно поместить различные элементы пользовательского интерфейса и другие контейнеры. Компоновка в WPF определяется типом используемого контейнера. Контейнеры компоновки WPF– это панели, порожденные от абстрактного класса System.Windows.Controls.Panel. Для компоновки в приложениях используются следующие классы:
- Grid и UniformGrid – размещают элементы в строки и колонки в соответствии с невидимой таблицей;
- StackPanel – размещает элементы в горизонтальные и вертикальные стопки. Этот контейнер часто используется для организации небольших участков более крупного и сложного окна;
- WrapPanel – размещает элементы управления в доступном пространстве, по одной строке или колонке;
- DockPanel - размещает элементы управления относительно одного из своих внешних краев;
- Frame – аналогичен StackPanel, но является предпочтительным способом упаковки содержимого для переходов на страницы.
Grid является наиболее мощным контейнером в WPF. Большая часть всего, что можно сделать с помощью других контейнеров компоновки, можно выполнить в Grid. Grid является идеальным инструментом для разделения окна (страницы) на более мелкие области, которыми можно будет управлять с помощью других панелей.
Grid распределяет элементы по сетке невидимых строк и столбцов. В одну ячейку сетки целесообразно помещать один элемент, который при необходимости может быть сам другим контейнером компоновки, в котором можно создать собственную группу элементов управления.
Панель StackPanel является одним из простейших контейнеров компоновки. Данная панель укладывает свои дочерние элементы в одну строку или колонку.
Контейнер UniformGrid, в отличие от Grid, требует установки только количества строк и столбцов и формирует ячейки одинакового размера, которые занимают всё доступное пространство окна (страницы) или элемента внешнего контейнера.
WrapPanel в зависимости от свойства Orientation упорядочивает элементы управления горизонтально ( Horizontal ) или вертикально ( Vertical ), заполняя текущий размер панели. При горизонтальном расположении элементы управления могут переноситься на следующую строку, а при вертикальном – на следующий столбец.
Панель DockPanel осуществляет пристыковку элементов управления к одной из своих сторон в зависимости от значения свойства Dock, которое может принимать значения Left, Right, Top или Bottom. Так если элемент управления был пристыкован к верхней части DockPanel, то он растягивается и будет занимать всю ширину панели, принимая такую высоту, какая определена параметром MaxHeight.
Frame является элементом управления содержимым, который предоставляет возможность перехода к содержимому и его отображения. Frame можно разместить внутри другого содержимого, как и другие элементы управления и элементы. Содержимое может быть любым типом объекта .NET Framework и файлов HTML. Обычно Frame используется для упаковки содержимого определяющего переходы на страницы.
Свойства компоновки определяются контейнером, но дочерние элементы также оказывают на неё определенное влияние. Панели компоновки работают в согласии со своими дочерними элементами благодаря следующим свойствам:
- HorizontalAlignment и VerticalAlignment – определяет, как дочерний элемент позиционируется внутри компоновки, когда имеется дополнительное пространство по горизонтали/вертикали;
- Margin – добавляет пустое пространство вокруг элемента;
- MinWidth и MaxWidth – устанавливает максимальные размерности для элемента;
- Width и Height – явно устанавливает размеры элемента.
В WPF существуют контейнеры, которые располагают элементы управления в соответствии заданными координатами, заданными размерами. Это контейнеры Canvas и InkCanvas. Данные контейнеры в большей степени предназначены для визуализации графических примитивов и фигур.
Элементы управления содержимым
Элементы управления предназначены для поддержки интерактивной связи с пользователем. Они могут принимать фокус и получать входные данные от клавиатуры или мыши.
Элементы управления содержимым являются специализированным типом элементов управления, которые могут хранить некоторое содержимое – один или несколько элементов. Все элементы управления содержимым являются наследниками класса ContentControl ( рис. 2.3).
Класс ContentControl наследуется от класса System.Windows.Control, который наделяет его и все дочерние классы базовыми характеристиками, которые:
- позволяют определять содержимое внутри элемента управления;
- позволяют определять порядок перехода с использованием клавиш табуляции;
- поддерживают рисование фона, переднего плана и рамки;
- поддерживают форматирование размера и шрифта текстового содержания.
Элементы управления имеют фон и передний план. Фоном, как правило, является поверхность элемента управления, а передним планом – текст. Цвет этих двух областей в WPF определяется с помощью свойств Background и Foreground. Эти свойства используют кисти – объект Brush. Это обеспечивает заливку содержимого фона и переднего плана сплошным цветом (класс кисти SolidColorBrush ) или градиентным, например с помощью класса кисти LinearGradientBrush.
Для задания фона кнопки с помощью объекта Brush необходимо свойству Color кисти SolidColorBrush присвоить значение, например Blue – голубой.
<Button>Кнопка A <Button.Background> <SolidColorBrush Color="Blue"></SolidColorBrush> </Button.Background> </Button>
В технологии WPF возможно применение сокращений для задания некоторых свойств. Так задание цвета фона или переднего плана можно выполнить следующим способом:
<Button Background="Black" Foreground="Red">Кнопка A</Button>
При этом синтаксический анализатор WPF автоматически создаст объекты SolidColorBrush с использованием заданных цветов, и будет применять созданные объекты для фона и переднего плана.
Если необходимо использовать другой тип кисти, например градиентный – LinearGradientBrush, то следует создавать объект кисти самостоятельно:
<Button>Кнопка A <Button.Background> <LinearGradientBrush> <LinearGradientBrush.GradientStops> <GradientStop Offset="0.0" Color="Blue"></GradientStop> <GradientStop Offset="1.0" Color="Red"></GradientStop> </LinearGradientBrush.GradientStops> </LinearGradientBrush> </Button.Background> </Button>
С помощью кисти рисуется рамка вокруг элемента управления. Это реализуется с помощью свойств BorderBrush и BorderThickness. При этом свойство BorderBrush принимает выбранную кисть, а BorderThickness – ширину рамки:
<Button Width="80" Height="30" Background="Red" BorderBrush="Blue" BorderThickness="5">Кнопка A</Button>
Технология WPF поддерживает прозрачность. Если на форме или странице расположить несколько элементов один поверх другого и для каждого из них задать различную степень прозрачности, то нижние элементы будут просматриваться через элементы, расположенные над ними. Это позволяет создавать многослойные анимационные объекты. Прозрачность можно задать двумя способами:
- с помощью свойства Opacity (непрозрачность), которое может принимать значение от 0 до 1. Значение 1 соответствует полностью непрозрачному цвету, а 0 – полностью прозрачному;
- с помощью полупрозрачного цвета через задание значения альфа-канала. Значение альфа-канала менее 255, является полупрозрачным.
Класс Control, от которого наследуются все элементы управления, определяет набор свойств, связанных со шрифтами:
- FontFamily – имя шрифта для использования в элементе контроля;
- FontSize – размер ширфта в единицах, не зависящих от устройства (каждая из них представляет собой 1/96 дюйма);
- FontStyle – представляет наклон текста;
- FontWeight – вес текста;
- FontStretch – величина на которую растягивается или сжимается текст.
При выборе шрифта переднего фона элемента управления необходимо указать полное имя семейства шрифтов:
<Button FontFamily="Times New Roman" FontSize="18">Кнопка A</Button>
При задании полужирного шрифта с наклоном необходимо задать следующие свойства:
<Button FontFamily="Times New Roman" FontSize="18" FontStyle="Italic" FontWeight="Bold"> Кнопка A</Button>
Многие элементы управления WPF являются элементами управления содержимым. Это элементы управления: Label, Button, CheckBox и RadioButton.
Метка – Label является простейшим элементом управления содержимым. Она принимает одиночную порцию содержимого, которую необходимо поместить внутри неё. Метка поддерживает мнемонические команды – клавишу быстрого доступа, передавая фокус связанному с ней элементу управления. Для поддержки этой функции используют свойство Target, которому присваивают выражение привязки. В выражении привязки необходимо указать другой элемент управления, на который будет переходить фокус при нажатии клавиши быстрого доступа.
<Label Target="{Binding ElementName = txtA}">Выбор _А</Label> <TextBox Name="txtA">Выбор текста</TextBox>
Символ подчеркивания в тексте метки указывает на клавишу быстрого доступа. Все мнемонические команды работают при одновременном нажатии клавиши <Alt> и заданной клавиши быстрого доступа. В приведенном выше коде при нажатии комбинации <Alt+A> фокус перейдет на элемент управления TextBox с именем txtA.
В WPF определены три класса: Button, CheckBox и RadioButton, которые наследуются от класса ButtonBase.
Класс ButtonBase определяет событие Click и добавляет поддержку команд, которые позволяют подключить кнопки для высокоуровневых задач приложения. В классе ButtonBase имеется свойство ClickMode, которое определяет когда кнопка генерирует событие Click в ответ на действия мыши. Значением, используемым по умолчанию, является ClickMode.Release, которое означает, что событие будет сгенерировано как при нажатии, так и при отпускании кнопки мыши. Для ClickMode.Press – событие будет генерироваться только при нажатии кнопки мыши, ClickModeHover – когда указатель мыши будет наведен на кнопку и задержен на ней.
Класс Button добавляет два свойства, доступные для записи: IsCancel и IsDefault.
При IsCancel = true кнопка будет работать как кнопка отмены окна и если нажать кнопку <Esc>, когда текущее окно находится в фокусе, то кнопка сработает.
Если IsDefault= true, то кнопка считается кнопкой по умолчанию.
Классы CheckBox и RadioButton наследуются от класса ToggleButton, который представляет кнопку, имеющую два состояния: нажата и отпущена. В классе имеются события Checked, Unchecked и Intermediate, которые генерируются при включении, выключении или переходе кнопки в неопределенное состояние.
Для кнопки CheckBox включение элемента управления означает отметку в нем флажка. Свойство IsChecked, наследуемое от класса ToggleButton, может принимать три значения: true (включено), false (выключено), null (неопределено, которое отображается в виде затененного окна, и используется для промежуточного состояния). Пример XAML-описания трех кнопок CheckBox приведен ниже.
<CheckBox Height="16" Name="checkBox1" Width="120" IsChecked="False" ClickMode="Release">Выбор А</CheckBox> <CheckBox Height="16" Name="checkBox2" Width="120" IsChecked="True" ClickMode="Press">Выбор Б</CheckBox> <CheckBox Height="16" Name="checkBox3" Width="120" IsChecked="{x:Null}" ClickMode="Hover">Выбор В</CheckBox>
Для кнопки RadioButton добавлено свойство GroupName, которое позволяет управлять расположением переключателей в группе. Из группы можно выбрать только один переключатель.
<GroupBox Header="Группа радиокнопок" Height="100" Name="groupBox1" Width="200"> <StackPanel> <RadioButton Height="16" Name="radioButton2" Width="120">Выбор Г</RadioButton> <RadioButton Height="16" Name="radioButton1" Width="120">Выбор Д</RadioButton> <RadioButton Height="16" Name="radioButton3" Width="120">Выбор Е</RadioButton> </StackPanel> </GroupBox>
Контекстные окна указателя ToolTip позволяют выводить всплывающие окна, когда пользователь наводит указатель мыши на определенный элемент. Данные окна в WPF относятся к группе элементов управления содержимым и поэтому в них можно помещать любое допустимое содержимое. Для вывода контекстного окна указателя не обязательно использовать класс ToolTip. Можно воспользоваться свойством ToolTip элемента управления, например для кнопки:
<Button ToolTip="Подсказка для кнопки А"></Button>
Элемент управления ScrollViewer обеспечивает прокрутку содержимого и используется, в основном, для упаковки контейнеров компоновки. С помощью этого элемента можно создавать прокручивающиеся панели.
Элемент UserControl предназначен для создания пользовательских элементов контроля, в которых можно объединять нескольно элементов управления.
Элемент Windows является элементом управления содержимым и используется для создания всех окон приложения.
Элемент HeaderedContentControl наследуется от класса ContentControl. HeaderedContentControl является родительским классом для элементов управления, которые имеют кроме содержимого и область заголовка.
Элемент управления GroupBox является окном с заголовком и используется для группирования связанных элементов управления, например радиокнопок.
Элемент управления TabItem представляет страницу для класса TabControl. Данный элемент отображает вкладку, которая активна в данный момент на панели TabControl.
Элемент управления Expander позволяет показывать и скрывать определенную область содержимого.