Главная » Silverlight » Привязка к выражению LINQ

0

Платформа Silverlight поддерживает синтаксис LINQ (Language Integrated Query — язык интегрированных запросов), введенный в .NET 3.5. Фактически LINQ — это SQL, встроенный в С#.

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

Полное описание синтаксиса LINQ выходит за рамки книги, однако вы многое узнае­те из простого примера. Предположим, в приложении определена коллекция products объектов Product и нужно создать вторую коллекцию, содержащую только те продукты, цена которых превышает 100 долларов. С помощью процедурного кода эту задачу мож­но решить следующим образом.

II Извлечение полного списка продуктов

List<Product> products = Арр.StoreDb.GetProducts();

// Создание второй коллекции на основе заданного условия

List<Product> matches = new List<Product>();

foreach (Product product in products)

{

if (product.UnitCost >= 100) {

matches.Add(product);

}

Аналогичный результат можно получить с помощью следующего выражения LINQ.

// Извлечение полного списка продуктов

List<Product> products = Арр.StoreDb.GetProducts ();

II Создание второй коллекции на основе заданного условия

IEnumerable<Product> matches = from product in products where product.UnitCost >= 100 select product ;

В данном примере выражение LINQ является запросом к коллекции, хранящейся в памяти. Обратите внимание на то, что в коде LINQ используются ключевые слова, не принадлежащие языку С#, тем не менее выражение LINQ является оператором С#.

Примечание. Полное описание LINQ можно найти в книге Джозефа С. Раттца UNQ. Язык интегрированных запросов в С# 2008 для профессионалов (Изд-во "Вильяме", 2008) или на веб-странице www .msdn .microsoft. com/en- us/netframework/aa904594. aspx. Большой набор примеров использования LINQ есть на странице www. msdn2.microsoft.com/en-us/vcsharp/aa336746.aspx.

Код LINQ неявно основан на интерфейсе IEnumerable<T>. Независимо от используе­мого источника данных, каждое выражение LINQ возвращает объект, реализующий ин­терфейс IEnumerable<T>. Интерфейс IEnumerable<T> наследует интерфейс IEnumerable, поэтому на странице Silverlight любое выражение LINQ можно связать так же, как обыч­ную коллекцию (рис. 16.7).

IstProducts.ItemsSource = matches;

Рис. 16.7. Фильтрация коллекции с помощью выражения LINQ; в спи­сок включены только продукты, удовлетворяющие заданному условию

В отличие от классов List и ObservableCollection, интерфейс IEnumerable<T> не предоставляет средств добавления или удаления элементов. Если эти средства нуж­ны, то сначала преобразуйте объект lEnumerable<T> в массив или коллекцию List с помощью метода ТоАггау () или ToList ().

Ниже приведен пример использования метода ToList () для преобразования резуль­тата запроса LINQ (см. предыдущий пример) в строго типизированную коллекцию List объектов Product.

List<Product> productMatches = matches.ToList ();

Вызов метода ToList () приводит к немедленному вычислению выражения LINQ. Конечный результат выражения — обычная коллекция List, с которой можно выполнять любые операции. Например, ее можно заключить в оболочку ObservableCollection, чтобы сделать ее редактируемой и генерировать события извещений для отображения изменений в связанных элементах управления.

Примечание. Строго говоря, метод ToList О — не метод, а расширение языка. Это означает, что он определен не в том классе, в котором используется. Технически он определен во вспомогательном классе System.Linq. Enumerable и доступен для всех объектов IEnumerble<T>. Однако он недоступен, если класса Enumerable нет в области видимости. Следовательно, приведенный выше код не компилируется, если не импортировано пространство имен System.Linq.

Вывод информации по категориям

Выше показано, что элементы страницы можно связать со свойством Selectedltem списка, чтобы вывести подробную информацию о выделенном элементе. Этот же способ используется для вывода информации по категориям. Например, можно создать стра­ницу, выводящую два списка: категорий и продуктов. Когда пользователь выделяет ка­тегорию в первом списке, во втором выводятся продукты, принадлежащие выделенной категории (рис. 16.8).

Рис. 16.8. Вывод списка продуктов, принадлежащих выделенной категории

Для примера необходим родительский объект данных, предоставляющий посредством свойства коллекцию связанных дочерних объектов данных. Например, можно создать класс Category, предоставляющий свойство Category. Products, которое содержит про­дукты, принадлежащие заданной категории. Как и класс Product, класс Category для ге­нерирования сообщений об изменениях реализует интерфейс iNotifyPropertyChanged.

public class Category : INotifyPropertyChanged {

private string categoryName;

public string CategoryName {

get { return categoryName; }

set { categoryName = value; OnPropertyChanged(new PropertyChangedEventArgs("CategoryName"));

)

}

private List<Product> products;

public List<Product> Products {

get { return products; } set { products = value;

OnPropertyChanged(new PropertyChangedEventArgs("Products"));

public event PropertyChangedEventHandler PropertyChanged;

public void OnPropertyChanged (PropertyChangedEventArgs e)

{

if (PropertyChanged != null) PropertyChanged(this, e);

}

public Category(string categoryName, ObservableCollection<Product> products)

{

CategoryName = categoryName; Products = products;

)

}

Чтобы применить класс Category, нужно изменить код доступа к данным. Теперь за­прос должен извлекать из базы данных информацию о продуктах и категориях. В при­мере, показанном на рис. 16.8, используется метод GetCategoriesWithProducts () веб- службы, возвращающий коллекцию объектов Category, в каждый из которых вложена коллекция объектов Product.

[OperationContract() ]

public List<Category> GetCategoriesWithProducts()

<                                                                                                                                      N

/ / Выполнение запроса о продуктах с помощью // хранимой процедуры GetProducts

SqlConnection con = new SqlConnection(connectionString); SqlCommand cmd = new SqlCommand("GetProducts", con) ; cmd.CommandType = CommandType.StoredProcedure;

// Временное сохранение результата в наборе DataSet SqlDataAdapter adapter = new SqlDataAdapter(cmd); DataSet ds = new DataSet(); adapter.Fill(ds, "Products");

// Выполнение запроса о категориях с помощью II хранимой процедуры GetCategories cmd.CommandText = "GetCategories"; adapter.Fill(ds, "Categories");

/ / Установка отношения между таблицами; это облегчает II извлечение продуктов заданной категории DataRelation relCategoryProduct = new DataRelation("CategoryProduct", ds.Tables["Categories"].Columns["CategorylD"],

ds.Tables["Products"].Columns["CategorylD"]); ds.Relations.Add(relCategoryProduct);

// Создание коллекции объектов Category List<Category> categories = new List<Category>(); foreach (DataRow categoryRow in ds.Tables["Categories"].Rows)

{

// Добавление вложенной коллекции объектов Product List<Product> products = new List<Product>(); foreach (DataRow productRow in categoryRow.GetChildRows(relCategoryProduct))

products.Add(new Product (productRow ["ModelNumber"] .ToStringO і productRow ["ModelName"] .ToStringO , Convert.ToDouble(productRow["UnitCost"]), productRow ["Description"] .ToStringO )) ;

}

categories.Add(new

Category (categoryRow["CategoryName"] .ToStringO , products)) ;

}

return categories;

Для вывода полученных данных нужны два следующих списка.

CListBox x:Name="IstCategories" DisplayMemberPath="CategoryName"

SelectionChanged="lstCategories_SelectionChanged"x/ListBox> CListBox x:Name="IstProducts" Grid.Row="l" DisplayMemberPath="ModelName"x/ListBox>

После получения коллекции от метода GetCategoriesWithProducts () необходимо установить свойство ItemsSource верхнеуровневого списка, чтобы вывести категории.

IstCategories.ItemsSource = е.Result;

Для вывода связанных продуктов нужно обработать событие щелчка на элементе первого списка, присвоив свойству ItemsSource второго списка значение свойства gat- egory. Products выбранного объекта Category.

IstProducts.ItemsSource = ((Category)IstCategories.Selectedltem).Products;

Источник: Мак-Дональд, Мэтью. Silverlight 3 с примерами на С# для профессионалов. : Пер. с англ. —- М. : ООО «И.Д. Вильяме», 2010. — 656 с. : ил. — Парал. тит. англ.

По теме:

  • Комментарии