Читалка блогов для Windows Phone 7. Часть 2. Чтение RSS ленты

В этой части я расскажу как в моей программе считывается RSS лента. Если на странице со списком блогов нажимаем на один из пунктов, то откроется окно в котором загрузятся последние записи блога, скорость загрузки зависит от скорости подключенного в телефоне интернета.
rssfeed

Еще в этом окне есть кнопочка Update, которая обновляет список и Edit по нажатию на которую откроется страница редактирования информации о RSS ленте. Как я уже писал в первой части, я нашел готовый класс для чтения RSSок, но я его немного изменил под свои потребности, свойство tags я удалил и добавил свойство Key, что бы знать ключ ячейки в памяти телефона, ленты с которой мы работаем и иметь туда доступ в любой момент.

Вот как он стал выглядит:
public class RSSFeed
{
    public string FeedURL { get; set; }
    public string FeedTitle { get; set; }
    public string FeedDetails { get; set; }
    public string Key { get; set; }     public XElement GetXElement()
    {
        XElement XML = new XElement("RSSFeed",
                                        new XElement("FeedURL", FeedURL),
                                        new XElement("FeedTitle", FeedTitle),
                                        new XElement("FeedDetails", FeedDetails));
        return XML;     } }
Это класс объекта всей ленты, еще есть класс одного пункта RSSItem, я тут тоже свойство tags заменил на pubDate:
public class RSSItem
{
    public string Title { get; set; }
    public string Description { get; set; }
    public string URL { get; set; }
    public string pubDate { get; set; }
}
И так, создаем объект класса RSSFeed и сразу присваиваем значения свойствам из класса parametrs, куда мы записывали значения перед загрузкой страницы. Еще создаем объект класса WebClient и переменную типа bool.
RSSFeed CurrentFeed = new RSSFeed
{
    FeedURL = new parametrs().URL,
    FeedTitle = new parametrs().Title,
    FeedDetails = new parametrs().Details,
    Key = new parametrs().Key
};
WebClient aWebClient = new WebClient(); bool update = true;
Теперь в методе PhoneApplicationPage_Loaded, который выполняется после загрузки страницы, проверяем или переменная update ровна true, для того что бы не загружать список повторно после того как мы возвращаемся с другой страницы, и присваиваем свойствам текстовых блоков значение FeedTitle и FeedDetails, добавляем обработчики событий и URL адрес для обьект aWebClient.
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
    if (update)
    {
        ListName.Text = CurrentFeed.FeedTitle;
        DetailsName.Text = CurrentFeed.FeedDetails;
        progressBar1.Value += 10;         aWebClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(aWebClient_DownloadProgressChanged);         aWebClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(aWebClient_DownloadStringCompleted);         aWebClient.DownloadStringAsync(new Uri(CurrentFeed.FeedURL));     } }
В методе aWebClient_DownloadStringCompleted создаем обьект класса XElement, и с помощью sql запроса вытягиваем нужные данные с xml файла и добавляем их в ListBox.
void aWebClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
    progressBar1.Value = 0;
    if (e.Error != null)         return;
    XElement MyXElement = XElement.Parse(e.Result);     listBox1.ItemsSource = from RSSElement in MyXElement.Descendants("item")                            select new RSSItem                            {                                Title = RSSElement.Element("title").Value,                                Description = RSSElement.Element("description").Value.Substring(0, 200),                                URL = RSSElement.Element("link").Value,                                pubDate = RSSElement.Element("pubDate").Value.Substring(0, 25)                            }; }
Один Item списка имеет в себе три текстовых блока.
<ListBox HorizontalAlignment="Left" Margin="6,23,0,0" Name="listBox1" Width="470" Height="600" VerticalAlignment="Top" SelectionChanged="listBox1_SelectionChanged" Foreground="Black" Background="Transparent">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Vertical" Height="150" Width="440" Background="Transparent" OpacityMask="Black" DataContext="{Binding}">
                <TextBlock TextWrapping="Wrap" Text="{Binding Title}" Foreground="#FFC8AB14" FontSize="28" Height="35" TextAlignment="Left" MaxWidth="440" Name="LbTitle"/>
                <TextBlock TextWrapping="Wrap" Text="{Binding Description}" FontSize="18" Height="97" TextAlignment="Left" MaxWidth="440"/>
                <TextBlock TextWrapping="Wrap" Text="{Binding pubDate}" FontSize="13" TextAlignment="Right" MaxWidth="440" DataContext="{Binding}" />
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
В методе aWebClient_DownloadProgressChanged добавляем обработку прогресс бара:
if (progressBar1.Value == 100) progressBar1.Value = 0; else progressBar1.Value += 10;
По нажатию на кнопку Update выполняется тот же код, что выполняется после загрузки страницы, только без проверки переменной update. Нажатие на кнопку Edit присваевает переменной update значение false, для того что бы при переходе назад на эту страницу не обновлялся лишний раз список; и переходит на страницу редактирования.
Теперь о редактировании информации об блоге. Окно выглядит вот так
editfeed
Сначала создаем строковою переменную и присваиваем ей значение ключа текущей ленты.
string Key = new parametrs().Key.ToString();
После загрузки страницы проверяем наличие данных в памяти по ключу и вытягиваем их в текстовые блоки, и на всякий случай, если нету данных  в памяти выдаем ошибку.
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
    if (IsolatedStorageSettings.ApplicationSettings.Contains(Key + Key + Key))
    {
        textBox1.Text = IsolatedStorageSettings.ApplicationSettings[Key + Key + Key].ToString();
        textBox2.Text = IsolatedStorageSettings.ApplicationSettings[Key].ToString();
        textBox3.Text = IsolatedStorageSettings.ApplicationSettings[Key + Key].ToString();
    }
    else
    {
        MessageBox.Show("No Result!", "Message", MessageBoxButton.OK);
    }
}
Еще тут есть обработка случайного нажатие на кнопку Back:
private void Press_Back(object sender, System.ComponentModel.CancelEventArgs e)
{
    if (MessageBox.Show("Are you sure?", "Message", MessageBoxButton.OKCancel) == MessageBoxResult.Cancel)
    {
        e.Cancel = true;
    }
}
При нажатии на кнопку Cancel программа просто возвращается на предыдущую страницу.
private void button3_Click(object sender, RoutedEventArgs e)
{
    if (NavigationService.CanGoBack)
        NavigationService.GoBack();
}
Кнопка Save записивает значение текстовых полей в IsolatedStorage и загружает страницу со списком блогов.
private void button1_Click(object sender, RoutedEventArgs e)
{
    IsolatedStorageSettings.ApplicationSettings[Key + Key + Key] = textBox1.Text.ToString();
    IsolatedStorageSettings.ApplicationSettings[Key] = textBox2.Text.ToString();
    IsolatedStorageSettings.ApplicationSettings[Key + Key] = textBox3.Text.ToString();
    NavigationService.Navigate(new Uri("/MainPage.xaml", UriKind.Relative));
}
Нажатие на кнопку Remove вызывает Message Box типа OKCancel.
removefeed
Проверяет если результат OK, то проверяется наличие данных под текущем ключом, удаляет их и переходит на страницу со списком блогов; если Cancel, то ничего не предпринимает.
private void button2_Click(object sender, RoutedEventArgs e)
{
    if (MessageBox.Show("Are you sure?", "Message", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
    {
        if (IsolatedStorageSettings.ApplicationSettings.Contains(Key + Key + Key))
        {
            IsolatedStorageSettings.ApplicationSettings.Remove(Key);
            IsolatedStorageSettings.ApplicationSettings.Remove(Key + Key);
            IsolatedStorageSettings.ApplicationSettings.Remove(Key + Key + Key);
        }
        else
        {
            MessageBox.Show("No Result!", "Message", MessageBoxButton.OK);
        }
        NavigationService.Navigate(new Uri("/MainPage.xaml", UriKind.Relative));
    }
}
Теперь чтение поста. Я долго думал как читать пост, сначала я занимался придумыванием велосипеда, но с этого почти ничего хорошего не вышло, потом я искал в интернете парсеры для html, но не один из мною найденных не мог корректно отображать данные поста (картинки, таблицы, списки) на винфоне. В конечном результате я решил просто добавить на страницу элемент WebBowser ну и передавать ему адрес поста. У меня получилась вот такая штука:
post
И так, при нажатии на пункт с постом на RSS ленте программа присваивает переменной update значение false, передает свойствам класса parametrs нужные параметры и переходит на страницу с постом.
private void listBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    // Откритие поста
    if (listBox1.SelectedItem == null)
    return;
    update = false;
    parametrs p = new parametrs();
    p.Title = ((RSSItem)listBox1.SelectedItem).Title.ToString();
    p.Details = ((RSSItem)listBox1.SelectedItem).Description.ToString();
    p.URL = ((RSSItem)listBox1.SelectedItem).URL.ToString();
    NavigationService.Navigate(new Uri("/Post.xaml", UriKind.Relative));
}
После загрузки страницы создается несколько обработчиков событий, включаются скрипты и браузеру передается адрес поста.
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
    parametrs p = new parametrs();
    Uri uri = new Uri(p.URL);
    try
    {
        progressBar1.Value += 30;
        webBrowser1.Navigating += new EventHandler<NavigatingEventArgs>(webBrowser1_Navigating);
        webBrowser1.Navigated += new EventHandler<NavigationEventArgs>(webBrowser1_Navigated);
        webBrowser1.IsScriptEnabled = true;
        webBrowser1.Navigate(uri);
    }
    catch
    {
    } }
Ну и еще тут есть два метода для обработки поведения прогресс бара:
private void webBrowser1_Navigating (object sender, NavigatingEventArgs e)
{
    progressBar1.Maximum = 100;
    if (progressBar1.Value == 100) progressBar1.Value = 0; else progressBar1.Value += 30;
}
private void webBrowser1_Navigated(object sender, EventArgs e)
{
    progressBar1.Value = 0;
}
Прогнозирую выложить приложение в Market Place, так что думаю что в следующей части напишу как этот процесс прошел.
Реклама

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s