Piszemy dla Metro - DP Feeds cz. 1
22.12.2011 | aktual.: 23.12.2011 13:54
Chciałbym w moim pierwszym wpisie mojego bloga na DP zaprezentować wam w jaki sposób pisze się aplikacje dla interfejsu Metro, który zadebiutuje wraz z pojawieniem się w 2012 roku nowego systemu operacyjnego firmy Microsoft o kodowej nazwie "Windows 8".
Pokażę wam jak stworzyć czytnik RSS wiadomości z portalu DobreProgramy, oparty o nowy interfejs Metro. Aby rozpocząć przygodę z pisaniem aplikacji dla Windows 8 należy pobrać udostępnioną publicznie we wrześniu wersję Windows Developer Preview nowego systemu operacyjnego wraz z potrzebnymi narzędziami. Wszystko co trzeba znajdziecie tutaj: Windows 8 Developer Preview with developer tools English, 64‑bit (x64) Windows 8 Developer Preview with developer tools English, 64‑bit (x64) zawiera wczesną wersję systemu Windows 8 wraz z narzędziem Visual Studio 11, które umożliwi nam dalszą zabawę.
A więc zaczynamy.
Uruchamiamy edytor Visual Studio i wybieramy "New Project"
Następnie wybieramy typ "Application" oraz wpisujemy nazwę naszego programu (DP Feeds) w polu "Name:" Visual Studio utworzyło nam odpowiedni szablon aplikacji, nie będę tutaj wnikał w konstrukcję samego szablonu, po odpowiednie info zapraszam na MSDN
Obecnie okno Visual Studio powinno wyglądać tak:
Narazie będzie interesować nas kod XAML oraz sam edytor wizualny ponieważ w tej części stworzymy sobie forme (stronę - jak ja to nazywam) aplikacji ze wszystkimi komponentami które będą później wypełnione odpowiednimi danymi. Nasze okno będzie składać się z nagłówka, lewej części w której będą wyświetlane bieżące tytuły newsów oraz daty publikacji na DP, po prawej stronie znajdzie się skrót treści wybranego wpisu. Klikając odpowiedni przycisk będzie można przejść do następnej "strony" naszej aplikacji, gdzie będzie wyświetlone okno przedstawiające całość newsa już w kontrolce WebView.
Kodujemy
Na wstępie zmienimy sobie typ okna głównego (strony) z "UserControl" na "Page" co uprości nam nawigację pomiędzy poszczególnymi stronami naszej aplikacji. Ja akurat preferuję taki sposób, potem wyjaśnię troszkę w czym rzecz gdy będziemy budowali drugą stronę programu na której znajdzie się mini przeglądarka w której będzie można obejrzeć cały, wybrany news z DP łącznie z komentarzami.
Zmiany dokonujemy w następujący sposób: w edytorze XAML zmieniamy wpis:
[code=] <UserControl x:Class="DP_Feeds_X.MainPage" .................. .................. </UserControl>[/code]
na
[code=] <Page x:Class="DP_Feeds_X.MainPage" .................. .................. </Page> [/code]
Następnym krokiem będzie zdefiniowanie stylu czcionki nagłówka naszej strony głównej aplikacji oraz samego stylu nagłówka. W tym celu pod linijką:
[code=]d:DesignHeight="768" d:DesignWidth="1366">[/code]
umieszczamy następujący kod:
[code=] <UserControl.Resources> <SolidColorBrush x:Key="HighlightBrush" Color="#FF26A0DA"/> </UserControl.Resources>[/code]
W powyższym przykładzie zdefiniowaliśmy sam styl naszego nagłówka, nie został on jeszcze jednak umieszczony na naszej "stronie" aplikacji i żadne zmiany nie są widoczne. Obecnie "strona" aplikacji jest czarna i nie znajdują się na niej żadne komponenty. Aby je tam umieścić wstawiamy odpowiedni kod pomiędzy linie:
[code=] <Grid x:Name="LayoutRoot" Background="#FF0C0C0C"> </Grid> [/code]
Wstępnie oddzielimy nasz nagłówek od reszty strony linią siatki. Aby to zrobić, pomiędzy powyższymi liniami umieszczamy kod:
[code=] <Grid.RowDefinitions> <RowDefinition Height="140"/> <RowDefinition Height="*"/> </Grid.RowDefinitions>[/code]
następnie pod tym kodem umieszczamy kod komponentu "TextBlock", który uwidoczni nasz nagłówek na "stronie" naszej aplikacji:
[code=] <Grid> <TextBlock x:Name="PageTitle" Text="DobreProgramy.pl" Style="{StaticResource PageTitleStyle}" Grid.Column="1" /> </Grid> [/code]
Cały nasz kod XAML "strony" powinien teraz wyglądać tak:
W polu Style="{StaticResource PageTitleStyle}" wskazaliśmy odnośnik do stylu czcionki oraz nagłówka, który zdefiniowaliśmy sobie na początku.
Tworzymy klasy
Zajmiemy się teraz stworzeniem odpowiednich klas oraz kodem który pobierze dla nas odpowiednie dane z kanału RSS strony DobreProgramy.pl
Przechodzimy zatem do kodu C# naszej strony, aby to zrobić rozwijamy gałąź MainPage.xaml która znajduje się w oknie Solution Explorer-a po prawej stronie okna głównego VS, następnie dwukrotnie klikamy na plik MainPage.xaml.cs. W tym momencie naszym oczom ukaże się edytor kodu źródłowego C# naszej strony.
Najpierw dodamy sobie dwie klasy:
public class FeedData { public string Title { get; set; } //using System.Collections.ObjectModel; private ObservableCollection<FeedItem> _Items = new ObservableCollection<FeedItem>(); public ObservableCollection<FeedItem> Items { get { return this._Items; } } } public class FeedItem { public string Title { get; set; } public string Content { get; set; } public DateTime PubDate { get; set; } public string Url { get; set; } }
Pamiętamy oczywiście o deklaracji System.Collections.ObjectModel który definiuje klasę ObservableCollection<T>.
Następnym krokiem jest dodanie funkcji która będzie wczytywać dane ze strumienia RSS portalu DobreProgramy, najpierw deklarujemy Windows.Web.Syndication następnie dodajemy funkcję GetFeedAsync(string feedUriString):
private async Task GetFeedAsync(string feedUriString) { // using Windows.Web.Syndication; SyndicationClient client = new SyndicationClient(); Uri feedUri = new Uri(feedUriString); try { SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri); FeedData feedData = new FeedData(); feedData.Title = feed.Title.Text; foreach (SyndicationItem item in feed.Items) { FeedItem feedItem = new FeedItem(); feedItem.Title = item.Title.Text; feedItem.PubDate = item.PublishedDate.DateTime; feedItem.Author = item.Authors[0].Name.ToString(); feedItem.Url = item.Links[0].Uri.ToString(); if (feed.SourceFormat == SyndicationFormat.Atom10) { feedItem.Content = item.Content.Text; } else if (feed.SourceFormat == SyndicationFormat.Rss20) { feedItem.Content = item.Summary.Text; } feedData.Items.Add(feedItem); DateTime date = feedItem.PubDate; string _title = item.Title.Text; string _tags = item.Authors[0].Name.ToString(); } this.DataContext = feedData; ItemListView.SelectedIndex = 0; } catch { // Log Error. } }
Do funkcji jako feedUriString przekazujemy adres kanału RSS ("http://feeds.feedburner.com/dobreprogramy/Aktualnosci") a samo jej wykonanie deklarujemy zaraz po funkcji inicjalizacji komponentów. Kod naszego głównej strony programu powinien teraz wyglądać tak:
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Threading.Tasks; using Windows.Foundation; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Data; using Windows.Web.Syndication; namespace DP_Feeds_Ex { partial class MainPage { public MainPage() { InitializeComponent(); GetFeedAsync("http://feeds.feedburner.com" +"/dobreprogramy/Aktualnosci"); } private async Task GetFeedAsync(string feedUriString) { // using Windows.Web.Syndication; SyndicationClient client = new SyndicationClient(); Uri feedUri = new Uri(feedUriString); try { SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri); FeedData feedData = new FeedData(); feedData.Title = feed.Title.Text; foreach (SyndicationItem item in feed.Items) { FeedItem feedItem = new FeedItem(); feedItem.Title = item.Title.Text; feedItem.PubDate = item.PublishedDate.DateTime; feedItem.Author = item.Authors[0].Name.ToString(); feedItem.Url = item.Links[0].Uri.ToString(); if (feed.SourceFormat == SyndicationFormat.Atom10) { feedItem.Content = item.Content.Text; } else if (feed.SourceFormat == SyndicationFormat.Rss20) { feedItem.Content = item.Summary.Text; } feedData.Items.Add(feedItem); DateTime date = feedItem.PubDate; string _title = item.Title.Text; string _tags = item.Authors[0].Name.ToString(); } this.DataContext = feedData; ItemListView.SelectedIndex = 0; } catch { // Log Error. } } } public class FeedData { public string Title { get; set; } //using System.Collections.ObjectModel; private ObservableCollection<FeedItem> _Items = new ObservableCollection<FeedItem>(); public ObservableCollection<FeedItem> Items { get { return this._Items; } } } public class FeedItem { public string Title { get; set; } public string Author { get; set; } public string Content { get; set; } public DateTime PubDate { get; set; } public string Url { get; set; } } }
Wyświetlamy nasze dane
Wróćmy teraz do kodu XAML budującego nasz interfejs "strony" głównej programu. Zabawę z tworzeniem interfejsu zakończyliśmy na stworzeniu nagłówka i oddzieleniu do od reszty "strony", czas aby dodać odpowiednią kontrolki które wyświetli (pobierze) dane z naszej dynamicznej kolekcji danych Items którą zadeklarowaliśmy w klasie FeedData i wypełniliśmy danymi newsów uzyskanymi z kanału RSS portalu DobreProgramy.
W tym celu w edytorze XAML naszej strony umieścimy kod komponentu ListView który będzie wyświetlał tytuły newsów na stronie, wraz z datą publikacji:
[code=] <ListView x:Name="ItemListView" ItemsSource="{Binding Path=Items}" Margin="8,0,0,10"> <ListView.ItemTemplate> <DataTemplate> <StackPanel> <TextBlock Text="{Binding Path=Title}" FontSize="24" Margin="5,0,0,0" TextWrapping="Wrap" /> <TextBlock Text="{Binding Path=PubDate}" FontSize="16" Margin="15,0,0,0"/> </StackPanel> </DataTemplate> </ListView.ItemTemplate> </ListView> [/code]
A także kod komponentu który wyświetli skrót (początek) newsa oraz pełny nagłówek:
[code=] <Grid DataContext="{Binding ElementName=ItemListView, Path=SelectedItem}" Grid.Column="1" Margin="25,8,0,-8"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <TextBlock Text="{Binding Path=Title}" FontSize="26" FontFamily="Segoe UI"/> <WebView x:Name="ContentView" Grid.Row="1" Margin="0,5,20,738" Opacity="0.5"/> </Grid> [/code]
Następnie dodajemy zdarzenie w kodzie naszego programu, które będzie wyświetlać fragment newsa po jego wybraniu z listy po lewej stronie. W tym celu, w edytorze "Design" naszej strony, dwukrotnie klikamy na pustą kontrolkę ListView (znajduje się ona z lewej strony):
Visual Studio wygeneruje odpowiedni kod zdarzenia, który uzupełnimy wpisem:
FeedItem feedItem = (sender as ListView).SelectedItem as FeedItem; if (feedItem != null) { ContentView.NavigateToString("<html><body bgcolor=\"#121212\"><font color=\"white\">" + feedItem.Content + "</font></body></html>"); }
I oto nasza wstępnie działająca aplikacja:
Życzę miłej zabawy :)
W następnej części dowiemy się jak stworzyć koleją "stronę" dla naszej aplikacji, troszkę o nawigowaniu między stronami oraz przekazywaniu pomiędzy nimi argumentów :)
Pełny kod źródłowy dostępny tutaj: http://www5.zippyshare.com/v/11483393/file.html