• Microsoft .NET
  • WPF и Silverlight
  • Элементы управления пользовательского интерфейса Silverlight (User Interface Controls)

Сводные данные и изолированное хранилище в Silverlight - Добавление веб-канала

ОГЛАВЛЕНИЕ

Добавление веб-канала

В приложении для примера при вводе адреса веб-канала пользователем и нажатии кнопки «Добавить» происходит выполнение кода, представленного на рис. 2. Сначала выполняется попытка создания URI из адреса, если это возможно, при помощи метода Uri.TryCreate. Если URI удается создать, то значение URI возвращается локальной переменной feedUri. В противном случае значение переменной feedUri остается равным «NULL», и выполняется окончание операции, предусмотренной кодом.

Рис. 2 Добавление веб-канала

private void btnAdd_Click(object sender, RoutedEventArgs e)
{
  Uri feedUri;
  Uri.TryCreate(txtAddress.Text, UriKind.Absolute, out feedUri);
  if (feedUri == null)
  return;

  LoadFeed(feedUri);
}

public void LoadFeed(Uri feedUri)
{
  WebClient request = new WebClient();
  request.DownloadStringCompleted += AddFeedCompleted;
  request.DownloadStringAsync(feedUri);
}

После создания URI выполняется метод LoadFeed, при котором при помощи запроса HTTP и класса WebClient собираются данные веб-канала. Создается экземпляр WebClient, после чего обработчику событий передается задание на обработку события DownloadStringCompleted. Когда метод DownloadStringAsync выполнен и готов возвратить данные, необходимо, чтобы в нем содержались сведения о том, к какому обработчику событий обращаться. Вот почему необходимо выполнить назначение обработчика событий (в данном случае AddFeedCompleted) до момента выполнения асинхронного события.

После завершения запроса обработчик событий AddFeedCompleted выполнит необходимые действия (см. рис. 3). Параметр DownloadStringCompletedEventArgs обладает свойствами Result и Error. Оба этих свойства необходимо проверить после каждого веб-запроса. Свойство e.Error будет иметь значение «NULL», если для этого запроса не произошло ошибок. Свойство e.Result содержит результаты веб-запроса. В случае с приложением, приводимым для примера, свойство e.Result будет содержать XM с данными потока.

Рис. 3 AddFeedCompleted

private void AddFeedCompleted(object sender, DownloadStringCompletedEventArgs e)
{
  if (e.Error != null)
  return;
  string xml = e.Result;
  if (xml.Length == 0)
  return;
  StringReader stringReader = new StringReader(xml);
  XmlReader reader = XmlReader.Create(stringReader);
  SyndicationFeed feed = SyndicationFeed.Load(reader);
  if (_feeds.Where(f => f.Title.Text == feed.Title.Text).ToList().Count > 0)
  return;
  _feeds.Add(feed); // This also saves the feeds to isolated storage
  ReBindAggregatedItems();
  txtAddress.Text = string.Empty;
}

После того как данные веб-канала будут собраны, их можно считать в класс System.ServiceModel.SyndicationFeed при помощи метода загрузки Load, принадлежащего классу SyndicationFeed. Обратите внимание, что при извлечении данных потока с использованием режима только чтения, возможно, оптимальным будет использовать LINQ при обработке XML, чтобы извлечь поток и поместить его в специальный объект, а не использовать класс SyndicationFeed. SyndicationFeed обладает большим набором функциональных возможностей, однако, если они не используются, возможно, не стоит добавлять лишний объем в XAP, ведь SyndicationFeed добавляет около 150 КБ к XAP, в то время как LINQ to XML добавляет только 40 КБ. То есть за дополнительные возможности SyndicationFeed приходится платить занимаемым на диске местом.

SyndicationFeed – это особый класс, в котором заложен способ репрезентации данных веб-канала (как формата RSS, так и AtomPub) в качестве объекта. Он обладает свойствами, которые описывают сам веб-канал, например Title и Description, а также атрибутом Items, который содержит переменную типа IEnumerable<SyndicationItem>. Каждый экземпляр класса SyndicationItem представляет объект веб-канала. Например, веб-каналы представлены экземплярами класса SyndicationFeed, а их подборки с атрибутом Items содержат отдельные материалы этих веб-каналов.

После того как класс SyndicationFeed загружен вместе с веб-каналом и его объектами, код, показаный на рис. 3 проверяет, собран ли уже этот веб-канал. Если это так, выполнение кода будет прекращено. В противном случае веб-канал добавляется к локальной коллекции ObservableCollection<SyndicationFeed>, называемой _feeds. При помощи метода ReBindAggregatedItems объекты веб-канала всех загруженных веб-каналов фильтруются, сортируются и перенаправляются в нижнюю сетку данных DataGrid. Поскольку класс WebClient выполнил веб-запрос по протоколу HTTP, обработчик событий AddFeedCompleted будет иметь доступ к веб-каналу интерфейса. Именно поэтому код, включенный в метод ReBindAggregatedItems, может выполнить привязку данных к элементу интерфейса DataGrid без помощи класса Dispatcher.