Преобразование информации
Язык C# поддерживает операции явного и неявного преобразования типов, причём эти операции могут быть перегружены в пользовательских типах.
Для выполнения взаимных преобразований данных базовых типов (числовые типы, bool, string и DateTime) предназначен статический класс System.Convert. Этот класс содержит набор методов вида To-ИмяТипа(), где ИмяТипа является именем CLR для базовых типов. Каждый такой метод перегружен и принимает аргумент любого базового типа. Выполнение метода может быть успешным или генерировать исключения InvalidCastException, FormatException, OverflowException.
Отметим, что для унификации операций преобразования все базовые типы явным образом реализуют интерфейс System.IConvertible. Это интерфейс содержит набор методов вида ToИмяТипа (), где ИмяТипа – имя CLR для базовых типов. Каждый такой метод принимает аргумент типа IFormatProvider.
Важными видами преобразований являются получение строкового представления объекта и получение объекта из строки. Для получения строкового представления объекта можно использовать виртуальный метод ToString(), определённый в классе System.Object. Однако часто требуется дать возможность выбора формата представления и учесть региональные стандарты. Для этой цели предназначен интерфейс System.IFormattable, который реализуют числовые типы, структура DateTime, класс Enum и некоторые другие типы.
public interface IFormattable
{
string ToString(string format, IFormatProvider formatProvider);
}
Первый параметр метода IFormattable.ToString() – это строка, сообщающая способ форматирования объекта.
Второй параметр метода IFormattable.ToString() – это поставщик формата. Это объект, реализующий интерфейс IFormatProvider.
Для получения данных типа по строке обычно используются статические методы, которые по соглашению об именовании называются Parse() и TryParse(). Если преобразование из строки невозможно, метод Parse() генерирует исключение, а TryParse() возвращает значение false. Методы Parse() и TryParse() есть во всех примитивных типах, классе Enum, в типах для работы со временем и во многих других типах. Обычно эти методы имеют перегруженные версии, принимающие в качестве аргумента поставщик формата.
Сравнение для выяснения равенства
Платформа .NET и язык C# предлагают несколько стандартных протоколов для выяснения равенства объектов. Наиболее общий подход при реализации проверки равенства заключается в переопределении виртуального метода Equals() класса Object. Базовая версия этого метода использует равенство ссылок. Тип ValueType перекрывает Equals(), чтобы реализовать равенство по значению, то есть проверку на совпадение всех соответствующих полей двух переменных типа значения.
Перекрытая версия Equals() должна удовлетворять следующим требованиям:
1. x.Equals(x) == true.
2. x.Equals(y) == y.Equals(x) .
3. (x.Equals(y) && y.Equals(z)) == true x.Equals(z) == true . 4. Вызовы x.Equals(y) возвращают одинаковое значение до тех пор, пока x и y остаются неизменными.
5. x.Equals( null) == false, если x != null.
6. Метод Equals() не должен генерировать исключений.
Так как метод Equals() класса Object принимает в качестве аргумента объект, для типов значений при вызове метода происходит операция упаковки. Чтобы избежать этого, тип может дополнительно к перекрытию Equals() реализовать интерфейс IEquatable<T>
Если создатель типа не реализовал эффективный метод проверки равенства, этот недостаток можно восполнить, применив подходящий подключаемый интерфейс . Интерфейсы System.Collections.Generic.IEqualityComparer<T> и System.Collections.IEqualityComparer позволяют организовать проверку объектов на равенство и вычисление хэш-кода объекта.
Сравнение для выяснения порядкаСтандартным способом сравнения для выяснения порядка является реализация типом интерфейсов IComparable и IComparable <T>
public interface IComparable
{
int CompareTo(object other);
}
public interface IComparable<in T>
{
int CompareTo(T other);
}
Оба интерфейса предоставляют одинаковый функционал. Универсальный интерфейс IComparable <T> избавляет от необходимости упаковки при работе с типами значений. Метод x.CompareTo(y) должен возвращать любое положительное число, если x «больше» y, отрицательное число, если x «меньше» y , и ноль, если x и y равны.
Базовые типы реализуют обе версии интерфейса IComparable. В типе string метод CompareTo() выполняет чувствительное к регистру сравнение строк с учётом региональных стандартов.
Кроме реализации IComparable и IComparable<T> тип может дополнительно перегружать операции < и >. Перегрузка операций сравнения обычно выполняется, если результат операции не зависит от контекста выполнения.
Как и в случае проверки на равенство, сравнение для выяснения порядка можно выполнить при помощи подключаемых интерфейсов. Для порядкового сравнения предназначены интерфейсы IComparer<T> и IComparer.
Компоновка
В WPF компоновка (layout) – это процесс размещения визуальных элементов на поверхности родительского элемента. Компоновка состоит из двух фаз:
1. Фаза измерения (measure). В этой фазе родительский контейнер запрашивает желаемый размер у каждого дочернего элемента, которые, в свою очередь, выполняют фазу измерения рекурсивно.
2. Фаза расстановки (arrange). Родительский контейнер сообщает дочерним элементам их истинные размеры и позицию, в зависимости от выбранного способа компоновки.
Рассмотрим некоторые свойства элементов WPF, связанные с процессом компоновки. Свойство Visibility, определённое в классе UIElement, управляет видимостью элемента. Это свойство принимает значение из перечисления System.Windows.Visibility : Visible – элемент виден на визуальной поверхности; Collapsed – элемент не виден на визуальной поверхности и не участвует в процессе компоновки; Hidden – элемент не виден на визуальной поверхности, но участвует в процессе компоновки («занимает место»).
В классе FrameworkElement определён набор свойств, ответственных за размер, отступы и выравнивание отдельного элемента: HorizontalAlignment, VerticalAlignment, Margin, MinWidth и
MinHeight, MaxWidth и MaxHeight, Width и Height.
При установке размеров в XAML можно указать единицу измерения: px (по умолчанию) – размер в единицах WPF (1/96 дюйма); in – размер в дюймах; cm – размер в сантиметрах; pt – размер в пунктах (1/72 дюйма).
Встроенные контейнеры компоновки
Контейнер компоновки – это класс, реализующий определённую логику компоновки дочерних элементов. Технология WPF предлагает ряд стандартных контейнеров компоновки:
1. Canvas.
2. StackPanel.
3. WrapPanel.
4. DockPanel.
5. Grid.
Все контейнеры компоновки являются панелями, которые унаследованы от абстрактного класса System.Windows.Controls.Panel.
Canvas – контейнер компоновки, реализующий позиционирование элементов путём указания фиксированных координат. Для задания позиции элемента следует использовать присоединённые свойства Canvas.Left , Canvas.Right, Canvas.Top , Canvas.Bottom . Эти свойства определяют расстояние от соответствующей стороны Canvas до ближайшей грани элемента.
StackPanel – популярный контейнер компоновки, который размещает дочерние элементы последовательно, по мере их объявления в контейнере. Свойство Orientation управляет направлением размещения дочерних элементов и принимает значения из одноимённого перечисления: Vertical (по умолчанию) или Horizontal.
WrapPanel – это контейнер компоновки, который во многом аналогичен StackPanel. Однако WrapPanel использует автоматический перенос элементов, для которых не хватает вертикального (горизонтального) пространства, в новый столбец (строку). WrapPanel поддерживает несколько свойств настройки:
Orientation – свойство аналогично одноименному свойству у StackPanel , но по умолчанию использует значение Horizontal.
ItemHeight – единая мера высоты для всех дочерних элементов. В рамках заданной единой высоты каждый дочерний элемент располагается в соответствие со своим свойством VerticalAlignment или усекается.
ItemWidth – единая мера ширины для всех дочерних элементов. В рамках заданной единой ширины каждый дочерний элемент располагается в соответствие со своим свойством HorizontalAlignment или усекается.
DockPanel ( док) реализует примыкание (docking) дочерних элементов к одной из своих сторон. Примыкание настраивается при помощи присоединённого свойства DockPanel.Dock, принимающего значения Left, Top, Right и Bottom (перечисление System.Windows.Controls.Dock). Примыкающий элемент растягивается на всё свободное пространство дока по вертикали или горизонтали (в зависимости от стороны примыкания), если у элемента явно не задан размер. Порядок дочерних элементов в доке имеет значение. Если в DockPanel свойство LastChildFill установлено в true (это значение по умолчанию), последний дочерний элемент занимает всё свободное пространство дока.
Grid – один из наиболее гибких и широко используемых контейнеров компоновки. Он организует пространство как таблицу с настраиваемыми столбцами и строками. Дочерние элементы размещаются в указанных ячейках таблицы. При настройке Grid необходимо задать набор столбцов и строк с помощью коллекций ColumnDefinitions и RowDefinitions. Для столбцов может быть указана ширина, для строк – высота. При этом допустимо использовать абсолютное значение, подбор по содержимому или пропорциональный размер . В последнем случае применяется символ * и необязательный коэффициент пропорциональности.
Дочерние элементы связываются с ячейками Grid при помощи присоединённых свойств Grid.Column и Grid.Row . Если несколько элементов расположены в одной ячейке, они наслаиваются друг на друга. Один элемент может занять несколько ячеек, определяя значения для присоединённых свойств Grid .ColumnSpan и Grid .RowSpan.
Контейнер Grid позволяет изменять размеры столбцов и строк при помощи перетаскивания, если используется элемент управления GridSplitter. Вот несколько правил работы с этим элементом:
1. GridSplitter должен быть помещён в ячейку Grid. Лучший подход заключается в резервировании специального столбца или строки для GridSplitter со значениями Height или Width , равными Auto.
2. GridSplitter всегда изменяет размер всей строки или столбца, а не отдельной ячейки. Чтобы сделать внешний вид GridSplitter соответствующим такому поведению, растяните его по всей строке или столбцу, используя присоединённые свойства Grid.ColumnSpan или Grid.RowSpan.
3. Изначально GridSplitter настолько мал, что его не видно. Дайте ему минимальный размер. Например, в случае вертикальной разделяющей полосы установите VerticalAlignment в Stretch, а Width – в фиксированный размер.
4. Выравнивание GridSplitter определяет, будет ли разделительная полоса горизонтальной (используемой для изменения размеров строк) или вертикальной (для изменения размеров столбцов). В случае горизонтальной разделительной полосы установите VerticalAlignment в Center (что принято по умолчанию). В случае вертикальной разделительной полосы установите HorizontalAlignment в Center .