ListView

99

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

Класс ListView унаследован от ListBox и дополняет его одной единственной деталью: свойством View. Свойство View представляет собой еще одну точку для создания многофункциональных списковых представлений. Если это свойство не установлено, элемент ListView ведет себя просто точно так же, как и его менее мощный предок — класс ListBox. Однако он становится гораздо более интересным, когда разработчик предоставляет объект представления, указывающий, каким должно быть форматирование и стили у элементов данных.

Формально свойство View указывает на экземпляр любого класса, унаследованного от ViewBase (который представляет собой абстрактный класс). Класс ViewBase удивительно прост: в действительности это не более чем оболочка, объединяющая вместе два стиля. Один из этих стилей применяется к элементу управления ListView (и указывается в свойстве DefaultStyleKey), в то время как другой применяется элементам внутри ListView (и указывается в свойстве ItemContainerDefaultStyleKey). Свойства DefaultStyleKey и ItemContainerDefaultStyleKey фактически стиль не предоставляют, а вместо этого они просто возвращают указывающий на него объект ResourceKey.

Сейчас наверняка интересно узнать, а зачем тогда вообще нужно свойство View — в конце концов, класс ListBox (как и все классы, унаследованные от ItemsControl) уже предлагает такие мощные возможности, как шаблоны данных и стили. Целеустремленные разработчики могут переделывать внешний вид элемента управления ListBox, предоставляя другой шаблон данных, другую панель компоновки и другой шаблон элемента управления.

Вообще говоря, для создания настраиваемых списков с множеством столбцов использовать класс ListView со свойством View необязательно. Точно такого же эффекта можно добиться и самостоятельно с помощью поддерживаемых классом ListBox шаблонов и стилей. Однако свойство View является полезной абстракцией. Ниже перечислены некоторые основные преимущества:

Представления, пригодные для многократного использования

ListView выделяет все касающиеся представления детали в один объект. Это упрощает создание представлений, не зависящих от данных и пригодных для применения с более чем одним списком.

Множественные представления

Отделение элемента управления ListView от объектов View также упрощает переключение между множеством различных представлений в одном и том же списке. (Например, именно такая технология применяется в проводнике Windows для получения различных представлений файлов и папок пользователя.) Точно такую же функциональную возможность можно создать и за счет динамического изменения шаблонов и стилей, но построить единственный объект, инкапсулирующий все детали представления, все-таки гораздо легче.

Более удобная организация

Объект представления упаковывает два стиля: один для корневого элемента управления ListView и еще один — для отдельных элементов в списке. Поскольку эти стили упаковываются вместе, очевидно, что эти два фрагмента связаны между собой и могут разделять определенные детали и взаимозависимости. Например, для основанного на столбцах элемента управления ListView это имеет большой смысл, поскольку ему необходимо, чтобы размещение заголовков столбцов совпадало с размещением предназначенных для этих столбцов данных.

Применение этой модели открывает замечательные возможности для создания ряда полезных готовых представлений, которыми бы могли пользоваться все разработчики. К сожалению, в настоящее время в состав WPF входит пока только один объект представления — объект GridView. Хотя его можно и удобно использовать для построения списков с множеством столбцов, при наличии каких-то других потребностей придется создавать собственное специальное представление. В последующих разделах будет показано, как делать то и другое.

Элемент GridView будет замечательным выбором, если нужно, чтобы отображаемые данные можно было конфигурировать, а представление в стиле сетки было одной из доступных для пользователя опций. Но если требуется, чтобы в сетке дополнительно поддерживались расширенная стилизация, выбор или редактирование, придется перейти к использованию полнофункционального элемента управления DataGrid.

Создание столбцов с помощью GridView

GridView — это класс, который наследуется от ViewBase и предоставляет списковое представление с множеством столбцов. Определяются эти столбцы путем добавления в коллекцию GridViewColumns объектов GridViewColumn.

GridView и GridViewColumn предлагают небольшой набор полезных методов, которые разработчик может использовать для настройки внешнего вида своего списка. Чтобы создать самый простой прямолинейный список (вроде Details (Список) в проводнике Windows), потребуется установить для каждого объекта GridViewColumn всего лишь два свойства: Header и DisplayMemberBinding. Свойство Header отвечает за размещаемый в верхней части столбца текст, а свойство DisplayMemberBinding содержит привязку, извлекающую из каждого элемента данных подлежащий отображению фрагмент информации.

Ниже приведен код разметки, необходимый для определения трех используемых в этом примере столбцов:

<ListView Name="lstw" Margin="5">
          <ListView.View>
                    <GridView>
                        <GridView.Columns>
                            <GridViewColumn Header="Имя" DisplayMemberBinding="{Binding Path=ModelName}"></GridViewColumn>
                            <GridViewColumn Header="Модель" DisplayMemberBinding="{Binding Path=ModelNumber}"></GridViewColumn>
                            <GridViewColumn Header="Цена" DisplayMemberBinding="{Binding Path=UnitCost, StringFormat={}{0:C}}"></GridViewColumn>
                        </GridView.Columns>
                    </GridView>
          </ListView.View>
     </ListView>
ListView на основе сетки

Здесь есть несколько важных моментов, на которые стоит обратить внимание. Во-первых, размер ни одного из столбцов не является жестко закодированным. Вместо этого GridView устанавливает размер столбцов в соответствии с размером самого широкого видимого элемента (или столбца заголовка, если тот занимает больше места в ширину), что вполне логично для основанного на гибкой компоновке мира WPF. (Конечно, при наличии огромных значений столбцов это немного усложняет дело. В таком случае можно попробовать упаковать текст).

Во-вторых, свойство DisplayMemberBinding устанавливается с использованием полнофункционального выражения привязки, которое поддерживает все возможности, в том числе форматирование строк и конвертеры значений.

Изменение размера столбцов

Изначально GridView делает каждый столбец настолько широким, насколько необходимо для того, чтобы в нем могло уместиться самое больше видимое значение. Однако размер любого столбца можно легко изменить, щелкнув и перетащив край его заголовка. Дважды щелкнув на крае заголовка столбца, можно заставить GridViewColumn изменить свой размер самостоятельно на основании какого-либо видимого в нем в текущий момент содержимого.

Например, в случае обнаружения при прокрутке списка вниз элемента, усеченного из-за несоответствия его размера ширине столбца, можно просто дважды щелкнуть на правом крае заголовка этого столбца, и столбец автоматически расширится должным образом.

Для более точного управления размером столбца при его объявлении можно указать конкретную ширину:

<GridViewColumn Width="300" ... />

Это просто определяет начальный размер столбца. На возможность пользователя изменять размер столбца описанными выше способами это никак не влияет. К сожалению, свойства вроде MaxWidth и MinWidth класс GridViewColumn не поддерживает, так что ограничить пределы, до которых пользователь может изменять размеры столбцов, нельзя. Единственный вариант — предоставить новый шаблон для заголовка GridViewColumn и вообще отключить возможность изменения его размера.

Пройди тесты
Лучший чат для C# программистов