Элементы управления Silverlight: расширенные элементы управления
В "Элементы управления Silverlight: представления и компоновки" , "Элементы управления Silverlight: представления и компоновки", был представлен набор элементов управления Silverlight и проведен обзор таких основных элементов управления, как TextBox и CheckBox. Однако для современных насыщенных интерактивных приложений (RIAs) необходимы намного более сложные элементы управления, такие как таблицы с данными, календари и т.д. В данной лекции вы научитесь использовать эти элементы управления в своих Silverlight приложениях. Некоторые из этих элементов управления, такие как DataGrid (Таблица с данными), заслуживают отдельного рассмотрения, поэтому не ожидайте получить здесь полный API этих элементов управления. Однако в данной лекции предоставлено достаточно сведений об этих расширенных элементах управления, которые позволят понимать, что происходит при их использовании. Располагая этими знаниями, можно продолжать экспериментировать и изучать эти элементы управления уже самостоятельно.
Элемент управления DataGrid
Элемент управления DataGrid разработан для облегчения задачи по отображению данных в формате таблицы. Это сетка данных,а не просто сетка, потому что она может быть связана с источником данных. Более подробно отображение данных рассматривается в "Создание взаимодействующих с сервером приложений в Silverlight" , "Создание взаимодействующих с сервером приложений в Silverlight", но чтобы вы могли осознать мощь DataGrid, некоторые из методик работы с ним будут использованы здесь.
При добавлении элемента управления DataGrid в окно редактирования XAML, получаем такой XAML-код:
<UserControl xmlns:my="clr-namespace:System.Windows.Controls; assembly=System.Windows.Controls.Data" x:Class="SilverlightApplication1.Page" xmlns=" http://schemas.microsoft.com/client/2007" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="400" Height="300"> <Grid x:Name="LayoutRoot" Background = "White"> <my:DataGrid> </my:DataGrid> </Grid> </UserControl>
Пока что DataGrid не может делать практически ничего, поэтому добавим в него два свойства: имя и AutoGenerateColumns (Столбцы формируются автоматически), которое обеспечит автоматическое создание необходимых столбцов данных при привязке сетки к DataGrid. Вот как выглядит XAML для Data-Grid после этих дополнений:
<my:DataGrid x:Name="GrdHeadline" AutoGenerateColumns="True"> </my:DataGrid>
ВОТ И все, что требуется для подготовки DataGrid к использованию связанных данных. Прежде чем переходить к остальным свойствам, методам и событиям этого элемента управления, давайте выполним простую привязку данных. Будем использовать RSS-канал по адресу http://feeds.reuters.com/reuters/oddlyEnoughNews?format=xml .
Итак, в начале Page.xaml.cs добавляем ссылку на System.Net:
using System.Net;
Далее необходимо настроить объект WebClient (Веб-клиент) на чтение данных по этому URI и добавить обработчик события для обработки завершения загрузки данных. Для этого в конструктор Page добавляем следующий код:
WebClient client = new WebClient(); Uri uri = new Uri("http://feeds.reuters.com/reuters/topNews?format=xml"); client.DownloadStringCompleted + = new DownloadStringCompletedEventHandler( client DownloadStringCompleted); client.DownloadStringAsync(uri);
Теперь по завершении загрузки данных будет запускаться обработчик события
client DownloadStringCompleted. В этой функции будет использоваться специальный класс типа NewsHeadline (Заголовок новостей). Вот код этого класса:
public class NewsHeadLine { public string strHead { get; set; } public string strLine { get; set; } }
client DownloadStringCompleted использует библиотеки System.Xml.Linq, поэтому понадобится добавить ссылку на них. Для этого щелкните правой кнопкой мыши References и выберите Add Reference. На вкладке .NET вы увидите библиотеку System.Xml.Linq, как показано на рис. 8.1. Выберите ее и щелкните OK.
Чтобы код скомпилировался, в нем должна быть указана эта библиотека. Для этого просто добавляем данное выражение в начало Page.xaml.cs:
using System.Xml.Linq;
Итак, получаем код обработчика событий client DownloadStringCompleted:
void client DownloadStringCompleted( object sender, DownloadStringCompletedEventArgs e) { XDocument xmlHeadlines = XDocument.Parse(e.Result); var headlines = from story in xmlHeadlines.Descendants("item") select new NewsHeadLine { strHead = (string)story.Element("title"), strLine = (string)story.Element("link") }; GrdHeadline.ItemsSource = headlines; }
Этот код обеспечивает синтаксический разбор данных, возвращаемых в результате запроса к сервису (хранящихся в e.Result), в объект XDocument. После этого с помощью Linq данные выбираются из XDocument и создается коллекция заголовков. Затем эта коллекция присваивается как значение свойству ItemsSource (Источник элементов) элемента управления DataGrid. Результаты представлены на рис. 8.2.
В DataGrid возможны два режима выбора: одиночный, при котором можно выбирать по одной строке, и множественный, при котором при удержании клавиш Ctrl и/или Shift может быть выбрано несколько строк.
Эти режимы задаются с помощью свойства SelectionMode (Режим выбора), которое принимает значения DataGridSelectionMode.Single для одиночного выбора и DataGridSelectionMode.Extended для множественного.
При использовании единичного режима выбранный элемент сохраняется в SelectedItem. Если этот объект типа object, перед использованием он должен быть приведен к соответствующему типу. Вы видели, что сетка заполнялась элементами определенного нами класса NewsHeadLine.
Итак, для единичного выбора выбранные данные могут быть получены следующим образом:
NewsHeadLine theHeadline = GrdHeadline.SelectedItem as NewsHeadLine;
Когда установлен режим множественного выбора, можно использовать свойство SelectedItems, возвращающее коллекцию списков. Это очень просто сделать, вот код:
string strHead; string strLink; System.Collections.IList listOfItems = GrdHeadline.SelectedItems; foreach(NewsHeadLine newsHead in listOfItems) { strHead = newsHead.strHead; strLink = newsHead.strLine; }
В данном случае, свойство SelectedItems возвращает System.Collections.IList. После этого можно перебрать его элементы, извлекая каждый из объектов NewsHeadline и получая его данные.
При использовании любой таблицы, и DataGrid здесь не исключение, всегда полезно сделать ее более удобной для восприятия путем использования цветных полос, т.е. чередовать закрашенную и незакрашенную строки попеременно разными цветами или оттенками. В данном случае, чтобы сделать DataGrid полосатым, можно использовать свойства RowBackground (Фон строки) и AlternatingRowBack-ground (Чередующийся фон строки). В качестве значений этим свойствам задается цвет кисти следующим образом:
GrdHeadline. RowBackground = new SolidColorBrush(Colors.LightGray); GrdHeadline.Alternating RowBackground = new SolidColorBrush (Colors. Yellow);
Результат такого форматирования можно увидеть на рис. 8.3.
Возможно, вы обратили внимание, что столбцы добавляются в том порядке, в котором данные определены в классе NewsHeadLine. Однако порядок вывода данных на экран можно менять. Настройку по умолчанию можно переопределить свойством DisplayIndex (Индекс отображения). Например, в нашем DataGrid два столбца. В первом выводятся заголовки, во втором - ссылки. Их можно поменять местами следующим способом:
GrdHeadline.Columns[0]. DisplayIndex = 1; GrdHeadline.Columns[1].DisplayIndex = 0;
Более широкие возможности управления визуальным представлением данных в сетке предоставляет шаблон данных. Шаблон данных-это XAML, определяющий то, как должны быть организованы данные, включая привязку к конкретным полям. Например, в предыдущих примерах вывода каждая ячейка таблицы была связана с определенным элементом RSS-канала. Чтобы вывести два поля RSS-канала в одной ячейке, необходимо использовать шаблон данных. Рассмотрим следующий XAML:
<UserControl xmlns:my="clr-namespace:System.Windows.Controls; assembly=System.Windows.Controls.Data" x:Class="DataGrid.Page" xmlns=" http://schemas.microsoft.com/client/2007" xmlns:x="http://schemas.microsoft.com/winfx/2006/xa ml" Width="400" Height="300"> <Grid x:Name="LayoutRoot" Background = "White"> <my:DataGrid x:Name="GrdHeadline" AutoGenerateColumns="True"> <my:DataGrid.Columns> <my:DataGridTemplateColumn> <my:DataGridTemplateColumn.CellTemplate> <DataTemplate> <StackPanel Orientation = "Vertical"> <TextBlock Text="123"></TextBlock> <TextBlock Text="{Binding strHead}"></TextBlock> <TextBlock Text="{Binding strPubDate}"></TextBlock> </StackPanel> </DataTemplate> </my:DataGridTemplateColumn.CellTemplate> </my:DataGridTemplateColumn> <my:DataGridTemplateColumn> <my:DataGridTemplateColumn.CellTemplate> <DataTemplate> <TextBlock Text="{Binding strLine}"></TextBlock> </DataTemplate> </my:DataGridTemplateColumn.CellTemplate> </my:DataGridTemplateColumn> </my:DataGrid.Columns> </my:DataGrid> </Grid> </UserControl>
В этом XAML столбцы DataGrid заданы заранее с помощью элемента <my:DataGrid.Columns>. Мы можем переопределить шаблон для столбцов по умолчанию, когда в ячейке выводится одно поле, задавая для каждой ячейки <my:DataGridTemplateColumn.CellTemplate>, в котором имеется код, описывающий, как должна отображаться ячейка.
Как видите, описано только две ячейки, поэтому данная таблица, независимо от количества полей данных, будет иметь только два столбца. Первый столбец, определенный шаблоном первой ячейки, будет представлен элементом StackPanel, содержащим три текстовых поля, в которых выводятся заданное в коде "123", связанное с данными свойство strHead класса NewsHeadline и связанное с данными свойство strPubDate того же класса NewsHeadline. StackPanel выводит эти поля друг над другом.
Второй столбец, описанный шаблоном второй ячейки, является простым TextBlock, связанным с полем strLine. Возможно, вы заметили, что здесь появилось еще одно поле, strPubDate, которого не было в исходном примере класса, поэтому описание класса и код привязки необходимо обновить. Вот новое описание класса:
public class NewsHeadLine { public string strHead { get; set; } public string strLine { get; set; } public string strDescription { get; set; } public string strPubDate { get; set; } }
И вот новый код привязки данных, который обеспечивает привязку дополнительных полей:
void client DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) { XDocument xmlHeadlines = XDocument.Parse(e.Result); var headlines = from story in xmlHeadlines.Descendants("item") select new NewsHeadLine { strHead = (string)story.Element("title"), strLine = (string)story.Element("link"), strDescription = (string)story.Element("description"), strPubDate = (string)story.Element("pubDate") }; GrdHeadline.ItemsSource = headlines; }
Чтобы увидеть новые данные, необходимо внести еще одну небольшую коррективу- изменить высоту строки. Сейчас в ней может отображаться только одна строка текста, в результате чего содержимое первой ячейки будет обрезано по вертикали. Также понадобиться отключить автоматическое определение столбцов, потому что мы хотим переопределить поведение привязки данных DataGrid по умолчанию. Это обеспечивает следующий код (поместите его в конструктор Page ):
GrdHeadline.AutoGenerateColumns = false; GrdHeadline.RowHeight = 60;
Теперь, после выполнения этого кода, на экран будет выведен DataGrid с ячейками, соответствующими заданным шаблонам (рис. 8.4). Выглядит не очень красиво, но замечательно иллюстрирует возможности управления представлением данных в элементе управления DataGrid.
Элемент управления DataGrid обладает богатейшим API, который заслуживает отдельного рассмотрения. Однако того, что было рассказано о нем на этих нескольких страницах, достаточно, чтобы понять, какую невероятную гибкость он обеспечивает. Вы сможете использовать эту базовую информацию для перехода на следующий уровень при создании собственных приложений Silverlight!