Teil 5: Erstellen eines Bloglesers (Windows Store-Apps mit C#/VB und XAML)

Sie erhalten hier eine Einführung in wichtigen Code und grundlegende Konzepte, die Sie beim Erstellen einer Windows Store-App mit C# oder Visual Basic benötigen. Zum Definieren der Benutzeroberfläche (UI) verwenden Sie XAML (Extensible Application Markup Language), während Sie für die App-Logik Ihre bevorzugte Programmiersprache verwenden können.

Wichtig  Dieses Lernprogramm ist für Microsoft Visual Studio 2012 und Windows 8 konzipiert. Teile des Lernprogramms funktionieren in Verbindung mit Microsoft Visual Studio 2013 und Windows 8.1 nicht ordnungsgemäß.

Falls Sie doch eine andere Sprache bevorzugen:

Roadmap: Wie hängt dieses Thema mit anderen zusammen? Siehe: Roadmap für Windows Store-Apps mit C# oder Visual Basic

Vorbereitung

  • Dies ist das letzte Lernprogramm in einer Lernprogrammreihe. Bevor Sie sich diesem Lernprogramm widmen, sollten Sie bereits Teil 1: Erstellen der App "Hello, world!", Teil 2: Verwalten von App-Lebenszyklus und -Zustand Teil 3: Navigation, Layout und Ansichten sowie Teil 4: Dateizugriff und -auswahl gelesen haben. In diesem Lernprogramm werden neue Konzepte vorgestellt und Konzepte aus früheren Lernprogrammen ergänzt.
  • Sie können dieses Lernprogramm auch dann absolvieren, wenn Sie die vorherigen Lernprogramme noch nicht gelesen haben. Es wird jedoch davon ausgegangen, dass Sie die Konzepte aus vorherigen Lernprogrammen verstehen und grundlegende Aufgaben in Microsoft Visual Studio ausführen können.
  • Es wird davon ausgegangen, dass Sie über Grundkenntnisse zu XAML und den Konzepten in der XAML-Übersicht verfügen.
  • Wir gehen davon aus, dass Sie das Standardfensterlayout in Visual Studio verwenden. Wenn Sie das Standardlayout ändern, können Sie es im Menü Fenster über den Befehl Fensterlayout zurücksetzen wiederherstellen.
  • Den vollständigen Code für dieses Lernprogramm finden Sie unter Blogleser: Vollständiger Code.

Lernziele

In diesem Lernprogramm besprechen wir kurz die Features, mit denen Sie Windows Store-Apps erstellen. Sie werden durch den Prozess zum Erstellen einer einfachen Blogleser-App geführt und lernen dabei die Konzepte kennen, auf denen die Entwicklung mit XAML beruht, einschließlich Layout, Steuerelementen, Vorlagen und Datenbindung. Sie erfahren, wie Sie die integrierten Seitenvorlagen und Navigationselemente aus Microsoft Visual Studio Express 2012 für Windows 8 verwenden, um schnell mit der Entwicklung der App beginnen zu können. Außerdem erfahren Sie, wie Sie mit den benutzerdefinierten Stilen das Aussehen der App verändern und die UI an verschiedene Layouts und Ansichten anpassen können. Abschließend besprechen wir kurz die Integration der App in Windows 8 und ihre Veröffentlichung im Windows Store. Nachdem Sie dieses Lernprogramm abgeschlossen haben, können Sie sofort Ihre eigenen Windows Store-Apps erstellen.

Hello World

Wenn Sie Ihre Windows Store-App mit C# oder Visual Basic erstellen, definieren Sie die UI in der Regel mit XAML. Die App-Logik schreiben Sie dabei in einer zugeordneten CodeBehind-Datei Ihrer bevorzugten Sprache. Das XAML-UI-Framework für Windows Store-Apps, die mit C# oder Visual Basic erstellt werden, befindet sich in den Windows.UI.Xaml.*-Namespaces der Windows-Runtime. Falls Sie Apps mit Windows Presentation Foundation (WPF), Microsoft Silverlight oder Silverlight für Windows Phone geschrieben haben, kennen Sie dieses Programmiermodell bereits und können damit Ihre Windows Store-App mit C# oder Visual Basic erstellen.

Das vorliegende Beispiel zeigt das XAML, mit dem die UI einer einfachen "Hello World"-App definiert wird, sowie die zugehörige CodeBehind-Seite. Schon dieses einfache Beispiel veranschaulicht verschiedene Konzepte, die für das XAML-basierte Programmiermodell wichtig sind: partielle Klassen, Layout, Steuerelemente, Eigenschaften und Ereignisse.



<Page
    x:Class="WindowsBlogReader.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:WindowsBlogReader"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <StackPanel>
            <Button Content="Click Me" Click="HelloButton_Click" />
            <TextBlock x:Name="DisplayText" FontSize="48" />
        </StackPanel>
    </Grid>
</Page>



using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;

namespace WindowsBlogReader
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            InitializeComponent();
        }

        private void HelloButton_Click(object sender, RoutedEventArgs e)
        {
            DisplayText.Text = "Hello, world";
        }
    }
}

Eine "Hello World"-App ist ein guter Ausgangspunkt. Allerdings lernen Sie nicht allzu viel dabei. Deswegen schlagen wir einen anderen Weg zum Erstellen von Windows Store-Apps ein. Die Beispiel-App, die Sie für die ersten Schritte verwenden, ist ein einfacher Blogleser, der die Daten aus einem RSS (Really Simple Syndication) 2.0- oder Atom 1.0-Feed herunterlädt und anzeigt. Die Feeds von der Website mit den Windows-Teamblogs eignen sich hier sicher gut als Beispiel. Am Ende wird die App wie folgt aussehen:

Navigationsbeispiel mit drei Seiten

Erstellen von Windows Store-Apps in Visual Studio

In diesem Abschnitt lernen Sie Folgendes:

  • Erstellen eines neuen Projekts vom Typ Windows Store-App in Visual Studio Express 2012 für Windows 8

Visual Studio ist eine leistungsstarke integrierte Entwicklungsumgebung (Integrated Development Environment, IDE) für das Entwickeln von Windows-Apps. Zu den vielen Möglichkeiten von Visual Studio gehören: Quelldateiverwaltung; integrierter Erstellungs-, Bereitstellungs- und Startsupport; die Bearbeitung von XAML, Visual Basic, C#, C++, Grafiken und Manifesten sowie Debugging. Visual Studio ist in mehreren Editionen erhältlich, Sie verwenden jedoch Visual Studio Express 2012 für Windows 8. Das Programm können Sie – ebenso wie das Windows Software Development Kit (SDK) für Windows 8 – kostenlos herunterladen. Damit haben Sie dann alles zur Hand, was Sie zum Erstellen, Verpacken und Bereitstellen Ihrer Windows Store-Apps brauchen.

Für den Anfang können Sie ein neues Windows Store-Projekt mit C# oder Visual Basic erstellen. Visual Studio Express 2012 für Windows 8 enthält verschiedene Vorlagen für Windows Store-Projekte, die Ihnen mit einer Fülle von Layouts einen schnellen Einstieg ermöglichen. Die Projektvorlage Blank App (XAML) enthält die grundlegenden Dateien, die Sie für alle Windows Store-Apps benötigen.

Weitere Infos über Visual Studio Express 2012 für Windows 8 finden Sie unter Entwickeln von Windows Store-Apps mit Visual Studio 2012.

BR211380.wedge(de-de,WIN.10).gifSo wird's gemacht: Erstellen eines neuen Windows Store-Projekts

  1. Öffnen Sie Visual Studio Express 2012 für Windows 8.
  2. Wählen Sie File (Datei) > New Project (Neues Projekt). Das Dialogfeld Neues Projekt wird geöffnet.
  3. Erweitern Sie im Bereich links unter Vorlagen den Eintrag Visual C# oder Visual Basic.
  4. Wählen Sie den Vorlagentyp Windows Store aus.
  5. Wählen Sie im mittleren Bereich Blank App (XAML) aus.
  6. Geben Sie einen Namen für das Projekt ein. Geben Sie dem Projekt den Namen "WindowsBlogReader".

    Dies ist ein neues Projekt in Visual Studio Express 2012 für Windows 8.

    Visual Studio-Dialogfeld "Neues Projekt"

  7. Klicken Sie auf OK. Ihre Projektdateien werden erstellt.

Wenn Sie ein Projekt erstellen, werden die Projektdateien von Visual Studio erstellt und im Projektmappen-Explorer angezeigt. Sehen wir uns einmal die Dateien und Ordner an, die die Vorlage Blank App (XAML) erstellt.

DateinameBeschreibung
Properties/AssemblyInfo (.vb or .cs)Enthält Metadaten zu Name und Version, die in die generierte Assembly eingebettet werden.
Package.appxmanifestEnthält Metadaten zur Beschreibung der App. Dazu gehören z. B. Anzeigename, Beschreibung, Logos und Funktionen.
Assets/*Bilder mit Standardlogo und Begrüßungsbildschirm, die Sie durch Ihre eigenen ersetzen können.
Common/StandardStyles.xamlEnthält Standardstile und Vorlagen für die App.
App.xaml, App.xaml.cs/vbDiese Dateien stellen die Logik der App dar. Die App-Klasse ist erforderlich, um die Benutzeroberfläche anzuzeigen.
MainPage.xamlDie Standardstartseite, die Sie für das Erstellen der Benutzeroberfläche verwenden.
MainPage.xaml.cs/vbDie CodeBehind-Datei mit der Logik für die Standardstartseite.

 

Weitere Informationen über diese Dateien und Vorlagen finden Sie unter Vorlagen für eine schnellere App-Entwicklung.

Abrufen von Daten in eine App

In diesem Abschnitt lernen Sie Folgendes:

  • Erstellen einer benutzerdefinierten Datenklasse
  • Asynchrones Abrufen eines RSS- oder Atom-Datenfeeds

Vor dem Erstellen der UI für die App schreiben wir den Code zum Abrufen der Blogfeeddaten, die dann in der UI angezeigt werden können. In den Windows-Teamblogs wird der Volltext der Blogbeiträge im RSS- und im Atom-Format verfügbar gemacht. In der Lese-App sollen Titel, Autor, Datum und Inhalt der jeweils neuesten Blogbeiträge angezeigt werden.

Zunächst einmal müssen Sie die Daten der einzelnen Beiträge herunterladen. Erfreulicherweise enthält die Windows-Runtime eine Gruppe von Klassen, mit denen die Feeddaten größtenteils bereits für Sie verarbeitet werden. Diese Klassen befinden sich im Windows.Web.Syndication-Namespace. Mit diesen Klassen können die Daten in der UI direkt angezeigt werden. Im Blogleser erstellen Sie jedoch eigene Datenklassen. Dadurch sind Sie flexibler und können RSS- und Atom-Feeds gleich behandeln.

Sie verwenden drei Klassen, um die Feeddaten in der Blogleser-App zu speichern und abzurufen. Alle drei Klassen werden in der Datei FeedData.cs/vb platziert. Die FeedData-Klasse enthält Informationen zum RSS- oder Atom-Feed. Die FeedItem-Klasse enthält Informationen zu einzelnen Blogbeiträgen im Feed. Die FeedDataSource-Klasse enthält eine Sammlung von Feeds und eine Methode zum Abrufen der Feeds aus dem Netzwerk.

BR211380.wedge(de-de,WIN.10).gifSo fügen Sie dem Projekt Datenklassen hinzu

  1. Wählen Sie Projekt > Klasse hinzufügen aus. Das Dialogfeld Neues Element wird geöffnet.
  2. Geben Sie "FeedData" als Name der Klassendatei ein.
  3. Klicken Sie auf Hinzufügen. Die neue Klassendatei wird erstellt.
  4. Kopieren Sie diesen Code in die Datei FeedData.cs/vb. Ersetzen Sie den gesamten Code in der Datei.
    
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Linq;
    using System.Threading.Tasks;
    using Windows.Web.Syndication;
    
    namespace WindowsBlogReader
    {
        // FeedData
        // Holds info for a single blog feed, including a list of blog posts (FeedItem).
        public class FeedData
        {
            public string Title { get; set; }
            public string Description { get; set; }
            public DateTime PubDate { get; set; }
    
            private List<FeedItem> _Items = new List<FeedItem>();
            public List<FeedItem> Items
            {
                get
                {
                    return this._Items;
                }
            }
        }
    
        // FeedItem
        // Holds info for a single blog post.
        public class FeedItem
        {
            public string Title { get; set; }
            public string Author { get; set; }
            public string Content { get; set; }
            public DateTime PubDate { get; set; }
            public Uri Link { get; set; }
        }
    
        // FeedDataSource
        // Holds a collection of blog feeds (FeedData), and contains methods needed to
        // retreive the feeds.
        public class FeedDataSource
        {
            private ObservableCollection<FeedData> _Feeds = new ObservableCollection<FeedData>();
            public ObservableCollection<FeedData> Feeds
            {
                get
                {
                    return this._Feeds;
                }
            }
    
            public async Task GetFeedsAsync()
            {
                Task<FeedData> feed1 =
                    GetFeedAsync("http://windowsteamblog.com/windows/b/developers/atom.aspx");
                Task<FeedData> feed2 =
                    GetFeedAsync("http://windowsteamblog.com/windows/b/windowsexperience/atom.aspx");
                Task<FeedData> feed3 =
                    GetFeedAsync("http://windowsteamblog.com/windows/b/extremewindows/atom.aspx");
                Task<FeedData> feed4 =
                    GetFeedAsync("http://windowsteamblog.com/windows/b/business/atom.aspx");
                Task<FeedData> feed5 =
                    GetFeedAsync("http://windowsteamblog.com/windows/b/bloggingwindows/atom.aspx");
                Task<FeedData> feed6 =
                    GetFeedAsync("http://windowsteamblog.com/windows/b/windowssecurity/atom.aspx");
                Task<FeedData> feed7 =
                    GetFeedAsync("http://windowsteamblog.com/windows/b/springboard/atom.aspx");
                Task<FeedData> feed8 =
                    GetFeedAsync("http://windowsteamblog.com/windows/b/windowshomeserver/atom.aspx");
                // There is no Atom feed for this blog, so use the RSS feed.
                Task<FeedData> feed9 =
                    GetFeedAsync("http://windowsteamblog.com/windows_live/b/windowslive/rss.aspx");
                Task<FeedData> feed10 =
                    GetFeedAsync("http://windowsteamblog.com/windows_live/b/developer/atom.aspx");
                Task<FeedData> feed11 =
                    GetFeedAsync("http://windowsteamblog.com/ie/b/ie/atom.aspx");
                Task<FeedData> feed12 =
                    GetFeedAsync("http://windowsteamblog.com/windows_phone/b/wpdev/atom.aspx");
                Task<FeedData> feed13 =
                    GetFeedAsync("http://windowsteamblog.com/windows_phone/b/wmdev/atom.aspx");
                Task<FeedData> feed14 =
                    GetFeedAsync("http://windowsteamblog.com/windows_phone/b/windowsphone/atom.aspx");
    
                this.Feeds.Add(await feed1);
                this.Feeds.Add(await feed2);
                this.Feeds.Add(await feed3);
                this.Feeds.Add(await feed4);
                this.Feeds.Add(await feed5);
                this.Feeds.Add(await feed6);
                this.Feeds.Add(await feed7);
                this.Feeds.Add(await feed8);
                this.Feeds.Add(await feed9);
                this.Feeds.Add(await feed10);
                this.Feeds.Add(await feed11);
                this.Feeds.Add(await feed12);
                this.Feeds.Add(await feed13);
                this.Feeds.Add(await feed14);
            }
    
            private async Task<FeedData> GetFeedAsync(string feedUriString)
            {
                Windows.Web.Syndication.SyndicationClient client = new SyndicationClient();
                Uri feedUri = new Uri(feedUriString);
    
                try
                {
                    SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri);
    
                    // This code is executed after RetrieveFeedAsync returns the SyndicationFeed.
                    // Process the feed and copy the data you want into the FeedData and FeedItem classes.
                    FeedData feedData = new FeedData();
    
                    if (feed.Title != null && feed.Title.Text != null)
                    {
                        feedData.Title = feed.Title.Text;
                    }
                    if (feed.Subtitle != null && feed.Subtitle.Text != null)
                    {
                        feedData.Description = feed.Subtitle.Text;
                    }
                    if (feed.Items != null && feed.Items.Count > 0)
                    {
                        // Use the date of the latest post as the last updated date.
                        feedData.PubDate = feed.Items[0].PublishedDate.DateTime;
    
                        foreach (SyndicationItem item in feed.Items)
                        {
                            FeedItem feedItem = new FeedItem();
                            if (item.Title != null && item.Title.Text != null)
                            {
                                feedItem.Title = item.Title.Text;
                            }
                            if (item.PublishedDate != null)
                            {
                                feedItem.PubDate = item.PublishedDate.DateTime;
                            }
                            if (item.Authors != null && item.Authors.Count > 0)
                            {
                                feedItem.Author = item.Authors[0].Name.ToString();
                            }
                            // Handle the differences between RSS and Atom feeds.
                            if (feed.SourceFormat == SyndicationFormat.Atom10)
                            {
                                if (item.Content != null && item.Content.Text != null)
                                {
                                    feedItem.Content = item.Content.Text;
                                }
                                if (item.Id != null)
                                {
                                    feedItem.Link = new Uri("http://windowsteamblog.com" + item.Id);
                                }
                            }
                            else if (feed.SourceFormat == SyndicationFormat.Rss20)
                            {
                                if (item.Summary != null && item.Summary.Text != null)
                                {
                                    feedItem.Content = item.Summary.Text;
                                }
                                if (item.Links != null && item.Links.Count > 0)
                                {
                                    feedItem.Link = item.Links[0].Uri;
                                }
                            }
                            feedData.Items.Add(feedItem);
                        }    
                    }
                    return feedData;
                }
                catch (Exception)
                {
                    return null;
                }
            }
    
            // Returns the feed that has the specified title.
            public static FeedData GetFeed(string title)
            {
                // Simple linear search is acceptable for small data sets
                var _feedDataSource = App.Current.Resources["feedDataSource"] as FeedDataSource;
    
                var matches = _feedDataSource.Feeds.Where((feed) => feed.Title.Equals(title));
                if (matches.Count() == 1) return matches.First();
                return null;
            }
    
            // Returns the post that has the specified title.
            public static FeedItem GetItem(string uniqueId)
            {
                // Simple linear search is acceptable for small data sets
                var _feedDataSource = App.Current.Resources["feedDataSource"] as FeedDataSource;
                var _feeds = _feedDataSource.Feeds;
    
                var matches = _feedDataSource.Feeds.SelectMany(group => group.Items).Where((item) => item.Title.Equals(uniqueId));
                if (matches.Count() == 1) return matches.First();
                return null;
            }
        }
    }
    
    
  5. Klicken Sie auf Erstellen > Projektmappe erstellen, um sicherzustellen, dass die Projektmappe ohne Fehler erstellt wird.

Abrufen der Feeddaten

Sehen wir uns einmal an, wie Blogfeeds heruntergeladen werden. Die Windows.Web.Syndication.SyndicationClient-Klasse ruft einen vollständig analysierten RSS- oder Atom-Feed ab, damit Sie die Daten verwenden können, ohne sich Gedanken über die XML-Analyse machen zu müssen. Um einen Feed mithilfe der SyndicationClient-Klasse herunterzuladen, müssen Sie die asynchrone RetrieveFeedAsync-Methode verwenden. Das asynchrone Programmiermodell wird in der Windows-Runtime häufig eingesetzt, damit die Apps reaktionsfähig bleiben. Für Sie wurde allerdings viel von der Komplexität, die asynchrone Methoden oft nach sich ziehen, bereits aus dem Weg geräumt.

Verwendung von await in C# und Visual Basic

Mit dem await-Schlüsselwort in C# und Visual Basic ähnelt der Code zum asynchronen Abrufen des Feeds dem des synchronen Abrufens. Befassen wir uns damit etwas genauer.

In der GetFeedsAsync-Methode rufen Sie GetFeedAsync für jeden Blogfeed auf, den Sie abrufen möchten. Falls möglich, übergeben Sie die URL für den Atom-Feed, da er Autorendaten einschließt, die Sie zeigen möchten. Wenn kein Atom-Feed vorhanden ist, wird der RSS-Feed verwendet. Jeden zurückgegebenen Blog fügen Sie der FeedDataSource.Feeds-Auflistung hinzu.

Da hierfür synchrone Methoden verwendet werden sollen, sieht Ihr Code folgendermaßen aus. Die GetFeed-Methode gibt hier ein FeedData-Objekt zurück. Die FeedData werden zurückgegeben und der Feeds-Auflistung hinzugefügt.



public void GetFeeds()
{
    FeedData feed1 = 
        GetFeed("http://windowsteamblog.com/windows/b/developers/atom.aspx");
    ...
    this.Feeds.Add(feed1);
    ...
}

Betrachten wir nun denselben Vorgang mit "asynchronen" Methoden und wie uns das await-Schlüsselwort dabei helfen kann. Zunächst ist zu beachten, dass Sie das async-Schlüsselwort der Methodensignatur hinzufügen. Das await-Schlüsselwort kann nur in einer als async definierten Methode verwendet werden. Der Rückgabetyp von GetFeedsAsync wird als Task angegeben.



public async Task GetFeedsAsync()
{
    Task<FeedData> feed1 = 
        GetFeedAsync("http://windowsteamblog.com/windows/b/developers/atom.aspx");
    ...
    this.Feeds.Add(await feed1);
    ...
}

Die GetFeedAsync-Methode gibt im asynchronen Code Task<FeedData> (oder Task(Of FeedData) in VB) zurück. Dieses Element stellt die FeedData dar, die schließlich als Rückgabewert der Methode verwendet werden sollen.

Wir haben nun folgenden Punkt im Code erreicht:


this.Feeds.Add(await feed1);

Der Aufruf von GetFeedAsync wurde ausgeführt, und eine Task<FeedData> wurde zurückgegeben. Anschließend wird die nächste Codezeile ausgeführt, um feed2 abzurufen. feed1 wird der Feeds-Auflistung jedoch erst hinzugefügt, nachdem das FeedData-Objekt tatsächlich an die wartende Task<FeedData> übergeben wurde. Dieser Vorgang wird gleich noch einmal ausführlicher betrachtet. Schauen wir uns nun an, was in der GetFeedAsync-Methode passiert.

Der Rückgabetyp von GetFeedAsync wird als Task<FeedData> angegeben. Hierdurch wird der Compiler aufgefordert, ein Task-Element zu erstellen, mit dem das von der Methode abgerufene FeedData-Objekt repräsentiert wird.


private async Task<FeedData> GetFeedAsync(string feedUriString)
{
...
}

In der Methode instanziieren Sie einen SyndicationClient und rufen dessen RetrieveFeedAsync-Methode auf, um den SyndicationFeed abzurufen, der die gewünschten RSS- oder Atom-Informationen enthält.


Windows.Web.Syndication.SyndicationClient client = new SyndicationClient();
Uri feedUri = new Uri(feedUriString);
...
    SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri);

Da es sich bei RetrieveFeedAsync um eine asynchrone Methode handelt, verwenden Sie das await-Schlüsselwort erneut. Mit dem await-Schlüsselwort wird der Compiler angewiesen, im Hintergrund viel für Sie zu erledigen. Der Compiler plant den Rest der Methode nach diesem Aufruf als Rückruf, der nach dem Zurückgeben des Aufrufs ausgeführt wird. Anschließend geht die Steuerung sofort wieder an den aufrufenden Thread, in der Regel den UI-Thread, sodass die App reaktionsfähig bleibt. Die Task<FeedData>, die das letztendliche Ergebnis dieser Methode darstellt, ein FeedData-Objekt, wird zu diesem Zeitpunkt an den Aufrufer zurückgegeben.

Wenn RetrieveFeedAsync den SyndicationFeed zurückgibt, wird der restliche Code in Ihrer Methode ausgeführt. Betont werden muss hier, dass er im selben Threadkontext ausgeführt wird, aus dem Sie den ursprünglichen Aufruf vorgenommen haben (dem UI-Thread). Sie benötigen daher keinen Verteiler, wenn Sie die UI in diesem Code aktualisieren möchten. Nach dem Abruf von SyndicationFeed kopieren Sie die Teile, die Sie benötigen, in die Datenklassen FeedData und FeedItem.



// This code is executed after RetrieveFeedAsync returns the SyndicationFeed.
// Process the feed and copy the data you want into the FeedData and FeedItem classes.
FeedData feedData = new FeedData();

if (feed.Title != null && feed.Title.Text != null)
{
    feedData.Title = feed.Title.Text;
}
if (feed.Subtitle != null && feed.Subtitle.Text != null)
{
    feedData.Description = feed.Subtitle.Text;
}
if (feed.Items != null && feed.Items.Count > 0)
{
    // Use the date of the latest post as the last updated date.
    feedData.PubDate = feed.Items[0].PublishedDate.DateTime;

    foreach (SyndicationItem item in feed.Items)
    {
        FeedItem feedItem = new FeedItem();
        if (item.Title != null && item.Title.Text != null)
        {
            feedItem.Title = item.Title.Text;
        }
        if (item.PublishedDate != null)
        {
            feedItem.PubDate = item.PublishedDate.DateTime;
        }
        if (item.Authors != null && item.Authors.Count > 0)
        {
            feedItem.Author = item.Authors[0].Name.ToString();
        }
        // Handle the differences between RSS and Atom feeds.
        if (feed.SourceFormat == SyndicationFormat.Atom10)
        {
            if (item.Content != null && item.Content.Text != null)
            {
                feedItem.Content = item.Content.Text;
            }
            if (item.Id != null)
            {
                feedItem.Link = new Uri("http://windowsteamblog.com" + item.Id);
            }
        }
        else if (feed.SourceFormat == SyndicationFormat.Rss20)
        {
            if (item.Summary != null && item.Summary.Text != null)
            {
                feedItem.Content = item.Summary.Text;
            }
            if (item.Links != null && item.Links.Count > 0)
            {
                feedItem.Link = item.Links[0].Uri;
            }
        }
        feedData.Items.Add(feedItem);
    }    
}
return feedData;

Wenn der Code die return-Anweisung erreicht, wird keine Rückgabe im eigentlichen Sinn wie bei einer synchronen Methode durchgeführt. Erinnern Sie sich noch daran, was von der Methode unmittelbar nach der "await"-Anweisung an den Aufrufer zurückgegeben wurde? Es wurde eine Task<FeedData> zurückgegeben, die letztendlich das Ergebnis der Methode darstellen soll. Hier erhalten Sie schließlich das Ergebnis. Die Zeile return feedData; übergibt das FeedData-Objekt, also das Ergebnis der Methode, an die Task<FeedData>, die darauf wartet.

Auf die Task wurde in dieser Zeile der GetFeedsAsync-Methode gewartet.


this.Feeds.Add(await feed1);

Wenn die Task das FeedData-Ergebnis erhält, auf das gewartet wurde, wird die Codeausführung fortgesetzt, und das FeedData-Objekt wird der FeedDataSource.Feeds-Auflistung hinzugefügt.

Verwenden der Daten in der App

Um die Daten in der App zu verwenden, erstellen Sie in App.xaml eine Instanz der Datenquelle als Ressource. Sie nennen die Instanz feedDataSource.

BR211380.wedge(de-de,WIN.10).gifSo fügen Sie einer App eine Ressource hinzu

  1. Doppelklicken Sie im Projektmappen-Explorer auf App.xaml. Die Datei wird im XAML-Editor geöffnet.
  2. Fügen Sie die Ressourcendeklaration <local:FeedDataSource x:Key="feedDataSource"/> dem ResourceDictionary-Stammelement nach der MergedDictionaries-Auflistung hinzu.

Dies ist das vollständige XAML für den Application.Resources-Abschnitt nach dem Hinzufügen der neuen Ressource.


    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>

                <!-- 
                    Styles that define common aspects of the platform look and feel
                    Required by Visual Studio project and item templates
                 -->
                <ResourceDictionary Source="Common/StandardStyles.xaml"/>
            </ResourceDictionary.MergedDictionaries>
            
            <local:FeedDataSource x:Key="feedDataSource"/>
        </ResourceDictionary>
    </Application.Resources>

Um die Feeds abzurufen, fügen Sie der Überschreibung der OnLaunched-Methode in der Datei App.xaml.cs/vb Code hinzu. Diese Methode wird immer dann aufgerufen, wenn der Benutzer die App startet.

An dieser Stelle fügen Sie der Methodendeklaration das async-Schlüsselwort hinzu, da Sie das await-Schlüsselwort in der Methode verwenden. Da eine aktive Internetverbindung erforderlich ist, damit von der App Feeds heruntergeladen werden können, suchen Sie mithilfe der NetworkInformation-Klasse eine Verbindung. Ist die App verbunden, laden Sie die Feeds herunter. Andernfalls benachrichtigen Sie den Benutzer. Sie fügen Code hinzu, um die FeedDataSource-Instanz der App abzurufen und zu überprüfen, ob darin bereits Feeds enthalten sind. Wenn dies nicht der Fall ist, rufen Sie die FeedDataSource.GetFeedsAsync-Methode auf, um die Feeds abzurufen.

BR211380.wedge(de-de,WIN.10).gifSo rufen Sie die Feeds ab

  1. Doppelklicken Sie im Projektmappen-Explorer auf App.xaml.cs/vb. Die Datei wird im Code-Editor geöffnet.
  2. Fügen Sie das async-Schlüsselwort der Signatur der OnLaunched-Methode hinzu.
    
    protected async override void OnLaunched(LaunchActivatedEventArgs args)
    
    
  3. Fügen Sie diesen Code der OnLaunched-Methode unmittelbar nach der Instanziierung der neuen Elemente Frame und rootFrame = New Frame() hinzu.
    
                    // Add this code after "rootFrame = new Frame();"
                    var connectionProfile = Windows.Networking.Connectivity.NetworkInformation.GetInternetConnectionProfile();
                    if (connectionProfile != null)
                    {
                        FeedDataSource feedDataSource = (FeedDataSource)App.Current.Resources["feedDataSource"];
                        if (feedDataSource != null)
                        {
                            if (feedDataSource.Feeds.Count == 0)
                            {
                                await feedDataSource.GetFeedsAsync();
                            }
                        }
                    }
                    else
                    {
                        var messageDialog = new Windows.UI.Popups.MessageDialog("An internet connection is needed to download feeds. Please check your connection and restart the app.");
                        var result = messageDialog.ShowAsync();
                    }
    
    

Dies ist der vollständige Code für die OnLaunched-Methode, nachdem Sie den Code hinzugefügt haben.


        protected async override void OnLaunched(LaunchActivatedEventArgs args)
        {
            Frame rootFrame = Window.Current.Content as Frame;

            // Do not repeat app initialization when the Window already has content,
            // just ensure that the window is active
            if (rootFrame == null)
            {
                // Create a Frame to act as the navigation context and navigate to the first page
                rootFrame = new Frame();

                // Add this code after "rootFrame = new Frame();"
                var connectionProfile = Windows.Networking.Connectivity.NetworkInformation.GetInternetConnectionProfile();
                if (connectionProfile != null)
                {
                    FeedDataSource feedDataSource = (FeedDataSource)App.Current.Resources["feedDataSource"];
                    if (feedDataSource != null)
                    {
                        if (feedDataSource.Feeds.Count == 0)
                        {
                            await feedDataSource.GetFeedsAsync();
                        }
                    }
                }
                else
                {
                    var messageDialog = new Windows.UI.Popups.MessageDialog("An internet connection is needed to download feeds. Please check your connection and restart the app.");
                    var result = messageDialog.ShowAsync();
                }

                if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
                {
                    //TODO: Load state from previously suspended application
                }

                // Place the frame in the current Window
                Window.Current.Content = rootFrame;
            }

            if (rootFrame.Content == null)
            {
                // When the navigation stack isn't restored navigate to the first page,
                // configuring the new page by passing required information as a navigation
                // parameter
                if (!rootFrame.Navigate(typeof(ItemsPage), args.Arguments))
                {
                    throw new Exception("Failed to create initial page");
                }
            }
            // Ensure the current window is active
            Window.Current.Activate();
        }

Sie können die App im Debugmodus erstellen und ausführen, um sicherzustellen, dass die Feeds ohne Fehler erstellt und abgerufen werden. Sind keine Fehler vorhanden, wird die App zwar ausgeführt, zeigt aber nur einen schwarzen Bildschirm an. Sind Fehler vorhanden, zeigt Visual Studio entsprechende Fehlerinformationen an. Weitere Informationen zum Ausführen von Apps in Visual Studio finden Sie unter Ausführen von Windows Store-Apps über Visual Studio.

BR211380.wedge(de-de,WIN.10).gifSo führen Sie die App im Debugmodus aus

  1. Gehen Sie wie folgt vor, um die App auszuführen:
    • Klicken Sie auf Debuggen > Debuggen starten.
    • Drücken Sie F5.
  2. So beenden Sie das Debuggen:
    1. Drücken Sie ALT+TAB, um zu Visual Studio zurückzukehren.
    2. Führen Sie in Visual Studio eine der folgenden Aktionen aus.
      • Klicken Sie auf Debuggen > Debuggen beenden.
      • Drücken Sie UMSCHALT+F5.

Nun erstellen Sie die UI zum Anzeigen der Daten.

Hinzufügen von Seiten und Navigationselementen

Sie müssen zum Anzeigen der Windows-Teamblogs der App Seiten hinzufügen und die Navigation zwischen diesen Seiten behandeln. Sie erstellen zuerst eine Seite, auf der alle Blogs des Windows-Teams aufgeführt werden. Wenn ein Benutzer einen Blog dieser Seite auswählt, navigieren Sie zu einer neuen Seite und laden die Liste der Beiträge für diesen Blog. Außerdem fügen Sie noch eine Detailseite hinzu, sodass einzelne Blogbeiträge gelesen werden können, ohne dass die Listenansicht Platz einnimmt.

Seitenvorlagen

Sie müssen glücklicherweise nicht jede Seite mit einer leeren Vorlage erstellen. Visual Studio Express 2012 für Windows 8 beinhaltet eine Reihe von praktischen Seitenvorlagen für unterschiedlichste Situationen. Hier finden Sie die verfügbaren Seitenvorlagen.

SeitentypBeschreibung
GruppendetailseiteZeigt Details für eine einzelne Gruppe und eine Vorschau jedes Elements in der Gruppe an.
Seite mit gruppierten ElementenZeigt gruppierte Auflistungen an.
ElementdetailseiteZeigt die Details eines Elements an und ermöglicht die Navigation zu benachbarten Elementen.
ElementseiteZeigt eine Auflistung von Elementen an.
Geteilte SeiteZeigt eine Liste mit Elementen und Details zum ausgewählten Element an.
Einfache SeiteEine leere Seite, die an verschiedene Ausrichtungen und Ansichten angepasst werden kann, mit einem Titel und einer Zurück-Schaltfläche.
Leere SeiteEine leere Seite für eine Windows Store-App.

 

Die Liste der Windows-Teamblogs wird mithilfe der Vorlage Elementseite angezeigt. Mithilfe der Vorlage Geteilte Seite zeigen Sie die Beiträge des jeweiligen Blogs sowie den Text des ausgewählten Beitrags an. Für die Detailseite verwenden Sie die Vorlage Einfache Seite.

BR211380.wedge(de-de,WIN.10).gifSo fügen Sie der App neue Seiten hinzu

  1. Klicken Sie auf Projekt > Neues Element hinzufügen. Das Dialogfeld Neues Element hinzufügen wird angezeigt.

    Hier sehen Sie das Dialogfeld Neues Element hinzufügen.

    Visual Studio-Dialogfeld Add New Item (Neues Element hinzufügen)
  2. Wählen Sie im linken Bereich unter Visual C# oder Visual Basic den Vorlagentyp Windows Store aus.
  3. Wählen Sie im mittleren Bereich den Seitentyp für Ihr Projekt aus. Wählen Sie die Vorlage Elementseite aus.
  4. Geben Sie einen Namen für die Seite ein. Geben Sie "ItemsPage.xaml" ein.
  5. Klicken Sie auf Hinzufügen.

    Wenn Sie der Vorlage Leere App erstmalig eine neue Seite hinzufügen, bei der es sich nicht um eine leere Seite handelt, zeigt Visual Studio ein Dialogfeld mit dem Hinweis an, dass Sie dem Projekt fehlende Dateien hinzufügen müssen. Klicken Sie auf Ja, um die entsprechenden Dateien hinzuzufügen. Ihrem Projekt werden im Ordner Common Dateien für einige Hilfsklassen hinzugefügt.

    Die XAML- und CodeBehind-Dateien für Ihre Seite werden dem Projekt hinzugefügt.

  6. Klicken Sie auf Erstellen > Projektmappe erstellen, um die App zu erstellen. Für die neue Seite tritt im Designer ein Fehler auf, solange Sie die erforderlichen Hilfsklassen nicht erstellen.
  7. Wiederholen Sie die Schritte 1-5, um eine geteilte Seite hinzuzufügen.
    • Wählen Sie in Schritt 3 die Vorlage Geteilte Seite aus.
    • Geben Sie der Seite in Schritt 4 den Namen "SplitPage.xaml".
  8. Wiederholen Sie die Schritte 1-5, um eine einfache Seite hinzuzufügen.
    • Wählen Sie in Schritt 3 die Vorlage Einfache Seite aus.
    • Geben Sie der Seite in Schritt 4 den Namen "DetailPage.xaml".

Wenn Sie Ihrem Projekt die Seitenvorlagen hinzufügen und einen Blick auf das XAML und die CodeBehind-Datei werfen, wird sofort klar, dass diese Seitenvorlagen Ihnen viel Arbeit abnehmen. Man kann sogar fast den Überblick verlieren. Sehen wir uns deshalb einmal genauer an, was in den Seitenvorlagen steckt. Alle XAML-Seitenvorlagen für Windows Store-Apps haben dasselbe Format.

Das XAML für die Seitenvorlagen umfasst drei Hauptabschnitte:

RessourcenStile und Datenvorlagen für die Seite werden im Abschnitt Resources definiert. Darauf gehen wir im Abschnitt Erzielen eines einheitlichen Aussehens mit Stilen noch genauer ein.
App-InhaltDie Steuerelemente und der Inhalt der App-UI werden im Stammlayoutpanel definiert.
Visual State-ManagerAnimationen und Übergänge, mit denen die App an unterschiedliche Layouts und Ausrichtungen angepasst wird, werden im Abschnitt VisualStateManager definiert. Mehr dazu erfahren Sie im Abschnitt Anpassung an verschiedene Layouts.

 

Die verwendeten Vorlagenseiten wurden alle von der LayoutAwarePage-Klasse abgeleitet. Sie bieten standardmäßig alle wesentlich mehr Funktionen als die Leere Seite, die für MainPage.xaml in einer leeren App verwendet wird. LayoutAwarePage ist eine Implementierung von Page, die wichtige Funktionen für die Entwicklung von Windows Store-Apps bereitstellt:

  • Mithilfe der Zuordnung des Ansichtszustands einer Anwendung zum visuellen Zustand kann die Seite an verschiedene Auflösungen, Ausrichtungen und Ansichten angepasst werden.
  • Die Ereignishandler GoBack und GoHome unterstützen die einfache Navigation.
  • Ein Standardansichtsmodell stellt eine einfache bindbare Datenquelle bereit.
  • Die SaveState- und die LoadState-Methode werden mit der SuspensionManager-Klasse verwendet, um den Sitzungszustand der App zu verwalten.

Die Seitenvorlagen verwenden auch Stile und Vorlagen aus StandardStyles.xaml, um Designrichtlinien für Windows Store-Apps anzuwenden. Sie verwenden einige dieser Stile als Ausgangspunkt und ändern Kopien dieser Stile, um das Aussehen der App anzupassen.

Navigation zwischen Seiten

Das XAML-UI-Framework verfügt über ein integriertes Navigationsmodell, das Frame- und Page-Elemente verwendet und wie die Navigation in einem Webbrowser funktioniert. Das Frame-Steuerelement hostet Page-Elemente. Mit dem zugehörigen Navigationsverlauf können Sie außerdem zwischen den besuchten Seiten wechseln. Bei der Navigation können Daten zwischen den Seiten übergeben werden.

Navigieren zur ItemsPage

In Projektvorlagen von Visual Studio ist ein Frame namens rootFrame als Inhalt des App-Fensters festgelegt. Dieser Frame hostet jede Page in der App. Befassen wir uns nun mit dem relevanten Code in App.xaml.cs/vb.



        protected async override void OnLaunched(LaunchActivatedEventArgs args)
        {
            Frame rootFrame = Window.Current.Content as Frame;

            // Do not repeat app initialization when the Window already has content,
            // just ensure that the window is active
            if (rootFrame == null)
            {
                // Create a Frame to act as the navigation context and navigate to the first page
                rootFrame = new Frame();

               ...

                // Place the frame in the current Window
                Window.Current.Content = rootFrame;
            }

            if (rootFrame.Content == null)
            {
                // When the navigation stack isn't restored navigate to the first page,
                // configuring the new page by passing required information as a navigation
                // parameter
                if (!rootFrame.Navigate(typeof(MainPage), args.Arguments))
                {
                    throw new Exception("Failed to create initial page");
                }
            }
            // Ensure the current window is active
            Window.Current.Activate();
        }

Dieser Code ruft ggf. einen vorhandenen Frame ab. Andernfalls wird ein neuer Frame erstellt und als Inhalt für das Fenster festgelegt. Im Anschluss erfolgt die Navigation zur MainPage. Da die erste Seite der App die ItemsPage sein soll, ändern Sie den Aufruf der Navigate-Methode und übergeben ItemsPage als Page, zu der navigiert werden soll.

BR211380.wedge(de-de,WIN.10).gifSo navigieren Sie zur ItemsPage

  1. Doppelklicken Sie im Projektmappen-Explorer auf App.xaml.cs/vb. Die Datei wird im Code-Editor geöffnet.
  2. Aktualisieren Sie wie hier gezeigt in der OnLaunched-Methode den Aufruf von rootFrame.Navigate, und übergeben Sie ItemsPage als ersten Parameter.
    
    
                if (!rootFrame.Navigate(typeof(ItemsPage), args.Arguments))
                {
                    throw new Exception("Failed to create initial page");
                }
    
    
    
  3. Drücken Sie F5, um die App zu erstellen und auszuführen. Nun wird die ItemsPage anstelle der standardmäßigen MainPage geladen.

    Hinweis  Die MainPage.xaml-Standarddatei wird in diesem Projekt nicht mehr benötigt. Sie kann daher problemlos entfernt werden.

Auf der Elementseite wird noch kein Inhalt angezeigt, da Sie noch keine Daten mit der Benutzeroberfläche verknüpft haben. Dies ist der nächste Schritt.

Laden der ItemsPage

Wenn ItemsPage geladen wird, müssen Sie die Instanz der App für die Datenquelle abrufen und mit der Benutzeroberfläche verknüpfen. Bei Seiten, die von LayoutAwarePage abgeleitet werden, können Sie die Daten mit dem DefaultViewModel verknüpfen, das von LayoutAwarePage bereitgestellt wird. Dieser Vorgang wird in der Überschreibung der LoadState-Methode ausgeführt.

BR211380.wedge(de-de,WIN.10).gifSo laden Sie Daten in die Elementseite

  1. Doppelklicken Sie zum Öffnen im Projektmappen-Explorer auf ItemPage.xaml.cs/vb.
  2. Fügen Sie diesen Code der LoadState-Methode hinzu.
    
                FeedDataSource feedDataSource = (FeedDataSource)App.Current.Resources["feedDataSource"];
    
                if (feedDataSource != null)
                {
                    this.DefaultViewModel["Items"] = feedDataSource.Feeds;
                }
    
    
  3. Drücken Sie F5, um die App zu erstellen und auszuführen.

Jetzt wird die ItemsPage mit einem Raster aller Blogs geladen. Es sieht ungefähr wie folgt aus, auch wenn die Elemente aufgrund der verwendeten Bildschirmauflösung unter Umständen anders angeordnet sind.

Elementseite

Navigieren zur SplitPage

Wenn der Benutzer einen Blog aus der Auflistung auswählt, wird von der Seite mit den Elementen zur geteilten Seite gewechselt. Hierzu dürfen die GridView-Elemente durch einen Klick nicht markiert werden, sondern müssen sich wie eine Schaltfläche verhalten. Um die GridView-Elemente klickbar zu machen, legen Sie die Eigenschaften SelectionMode und IsItemClickEnabled wie hier gezeigt fest. Dann fügen Sie einen Handler für das GridView-Ereignis von ItemClick hinzu.

BR211380.wedge(de-de,WIN.10).gifSo navigieren Sie zur SplitPage

  1. Doppelklicken Sie zum Öffnen im Projektmappen-Explorer auf ItemsPage.xaml.
  2. Wählen Sie das GridView-Steuerelement itemGridView aus.
  3. Erweitern Sie im Eigenschaftenpanel den Abschnitt Allgemein, und klicken Sie unten auf den Pfeil nach unten, um die erweiterten Eigenschaften anzuzeigen.
  4. Aktivieren Sie das Kontrollkästchen für die IsItemClickEnabled-Eigenschaft. Dadurch wird die Eigenschaft auf true festgelegt.
  5. Fügen Sie einen Handler für das ItemClick-Ereignis hinzu.
    1. Klicken Sie im Eigenschaftenpanel auf die Schaltfläche "Ereignisse" (Ereignisschaltfläche).
    2. Suchen Sie in der Ereignisliste nach dem ItemClick-Ereignis. Geben Sie im Textfeld für das Ereignis "ItemView_ItemClick" für den Namen der Methode ein, die das ItemClick-Ereignis behandelt.
    3. Drücken Sie die EINGABETASTE. Die Ereignishandlermethode wird erstellt und im Code-Editor geöffnet. Sie können nun Code hinzufügen, der beim Eintreten des Ereignisses ausgeführt werden soll.
    4. Fügen Sie diesen Code dem Ereignishandler ItemView_ItemClick in der CodeBehind-Seite hinzu.

      An dieser Stelle navigieren Sie zur geteilten Seite und übergeben den Titel des ausgewählten Feeds.

      
                  // Navigate to the split page, configuring the new page
                  // by passing the title of the clicked item as a navigation parameter
      
                  if (e.ClickedItem != null)
                  {
                      string title = ((FeedData)e.ClickedItem).Title;
                      this.Frame.Navigate(typeof(SplitPage), title);
                  }
      
      
  6. Wählen Sie in ItemsPage.xaml das ListView-Steuerelement itemListView aus.
  7. Klicken Sie im Eigenschaftenfenster auf die Eigenschaftenschaltfläche (Ereignisschaltfläche).
  8. Wiederholen Sie die Schritte 4 bis 5.3 für das itemListView-Steuerelement.

Wenn die App angedockt wird, wird die itemListView-Liste anstelle des Rasters angezeigt. Wir werden dies ausführlicher im Abschnitt Anpassen an verschiedene Layouts behandeln. Sie müssen vorerst nur die gleichen Änderungen an der ListView vornehmen, die Sie auch für die GridView vorgenommen haben, damit beide das gleiche Verhalten besitzen.

Um zwischen Seiten zu wechseln, verwenden wir die Methoden Navigate, GoForward und GoBack des Frame-Steuerelements. Für die Rückwärtsnavigation stellen die Seitenvorlagen von Visual Studio eine entsprechende Schaltfläche bereit. Der Handler für das Click-Ereignis von BackButton ruft die Frame.GoBack-Methode auf.

Die Navigate(TypeName, Object)-Methode ermöglicht die Navigation und das Übergeben eines Datenobjekts an die neue Seite. Sie verwenden diese Methode, um Daten zwischen Ihren Seiten zu übergeben. Der erste Parameter (typeof(SplitPage)) ist der Typname (Type) der Seite, zu der Sie wechseln. Der zweite Parameter ist das Datenobjekt, das Sie an die Seite übergeben, zu der Sie wechseln. In diesem Fall übergeben Sie den Titel des Elements, auf das geklickt wurde.

Grundsätzlich wäre es auch möglich, Ihre benutzerdefinierten Datenobjekte als Navigationsparameter zu übergeben. Diese würden jedoch nicht beibehalten und lösen zudem eine Ausnahme aus, wenn der Sitzungszustand der App mit der SuspensionManager-Klasse gespeichert wird. Um den Navigationszustand der App mit SuspensionManager zu speichern, dürfen nur einfache und serialisierbare Typen als Navigationsparameter übergeben werden. Sie übergeben daher den Titel des Elements und rufen das Element im Titel mit einer Methode in der FeedDataSource-Klasse ab.

Bevor Sie mit der geteilten Seite fortfahren, müssen Sie noch eine Änderung an der Elementseite vornehmen. Der Standardtitel der Seite lautet "My Application". Sie ändern diesen nun in "Windows Team Blogs".

BR211380.wedge(de-de,WIN.10).gifSo ändern Sie den Seitentitel

  1. Doppelklicken Sie zum Öffnen im Projektmappen-Explorer auf ItemsPage.xaml.
  2. Wählen Sie den TextBlock namens pageTitle aus.
  3. Klicken Sie im Eigenschaftenfenster auf die Eigenschaftenschaltfläche (Ereignisschaltfläche).
  4. Klicken Sie im Bereich Eigenschaften unter Allgemein auf den Eigenschaftsmarker für die Text-Eigenschaft. Das Eigenschaftenmenü wird geöffnet.

    Hinweis  Der Eigenschaftsmarker ist das kleine Feldsymbol rechts vom jeweiligen Eigenschaftswert. Der Text-Eigenschaftenmarker ist grün. Dies gibt an, dass der Marker auf eine Ressource festgelegt wurde.

  5. Klicken Sie im Eigenschaftenmenü auf Ressource bearbeiten.... Das Dialogfeld Ressource bearbeiten wird geöffnet.
  6. Ändern Sie im Dialogfeld Ressource bearbeiten den Wert von "My Application" in "Windows Team Blogs".
  7. Klicken Sie auf OK.

In ItemsPage.xaml ist der Seitentitel an eine statische Ressource mit dem Schlüssel AppName gebunden. Der Text in dieser Ressource wird in "Windows Team Blogs" aktualisiert. Das XAML sieht nun wie folgt aus.


<x:String x:Key="AppName">Windows Team Blogs</x:String>

Drücken Sie F5, um die App zu erstellen und auszuführen. Wenn Sie jetzt auf ein Element klicken, wird die geteilte Seite geladen. Die geteilte Seite ist aber leer, da Sie sie noch nicht mit den Daten verknüpft haben.

Laden der SplitPage

Auf der CodeBehind-Seite für SplitPage.xaml.cs/vb müssen Sie sich dem Objekt widmen, das soeben von der Elementseite übergeben wurde. Dazu setzen Sie erneut die LoadState-Methode außer Kraft. Diese Methode wurde dem Code der Seitenvorlage bereits hinzugefügt. Sie müssen deshalb nur noch Ihre Daten einbinden. Der navigationParameter enthält das von der Elementseite übergebene Datenobjekt. Das Objekt wird wieder in eine string umgewandelt und dann als Parameter an die FeedDataSource.GetFeed-Methode übergeben. Die zurückgegebenen Feeddaten werden mit dem Schlüssel Feed an DefaultViewModel übergeben. Außerdem wird die FeedData.Items-Eigenschaft mit dem Schlüssel Items an DefaultViewModel übergeben.

BR211380.wedge(de-de,WIN.10).gifSo laden Sie Daten in die geteilte Seite

  1. Doppelklicken Sie im Projektmappen-Explorer auf SplitPage.xaml.cs/vb, um das Element im Code-Editor zu öffnen.
  2. Fügen Sie diesen Code oben in der LoadState-Methode nach den "TODO"-Kommentaren hinzu.

    Tipp  Erweitern Sie den Bereich für die Seitenzustandsverwaltung, damit die LoadState-Methode angezeigt wird.

    
    
                // TODO: Assign a bindable group to this.DefaultViewModel["Group"]
                // TODO: Assign a collection of bindable items to this.DefaultViewModel["Items"]
                string feedTitle = (string)navigationParameter;
                FeedData feedData = FeedDataSource.GetFeed(feedTitle);
                if (feedData != null)
                {
                    this.DefaultViewModel["Feed"] = feedData;
                    this.DefaultViewModel["Items"] = feedData.Items;
                }
    
    

Hier ist die aktualisierte LoadState-Methode.



        protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
        {
            // TODO: Assign a bindable group to this.DefaultViewModel["Group"]
            // TODO: Assign a collection of bindable items to this.DefaultViewModel["Items"]
            string feedTitle = (string)navigationParameter;
            FeedData feedData = FeedDataSource.GetFeed(feedTitle);
            if (feedData != null)
            {
                this.DefaultViewModel["Feed"] = feedData;
                this.DefaultViewModel["Items"] = feedData.Items;
            }

            if (pageState == null)
            {
                // When this is a new page, select the first item automatically unless logical page
                // navigation is being used (see the logical page navigation #region below.)
                if (!this.UsingLogicalPageNavigation() && this.itemsViewSource.View != null)
                {
                    this.itemsViewSource.View.MoveCurrentToFirst();
                }
            }
            else
            {
                // Restore the previously saved state associated with this page
                if (pageState.ContainsKey("SelectedItem") && this.itemsViewSource.View != null)
                {
                    // TODO: Invoke this.itemsViewSource.View.MoveCurrentTo() with the selected
                    //       item as specified by the value of pageState["SelectedItem"]
                }
            }
        }

Drücken Sie F5, um die App zu erstellen und auszuführen. Wenn Sie nun auf die geteilte Seite navigieren, werden die Daten angezeigt, und Sie können in der Liste mit den Blogbeiträgen eine Auswahl treffen. Allerdings ist der Seitentitel immer noch leer. Darum kümmern Sie sich jetzt.

In der Visual Studio-Seitenvorlage geben die "TODO"-Kommentare Aufschluss darüber, wo Ihr Datenobjekt dem DefaultViewModel mit dem Group-Schlüssel hinzugefügt wird.



            // TODO: Assign a bindable group to this.DefaultViewModel["Group"]
            ...
                this.DefaultViewModel["Feed"] = feedData;


Einen Blogfeed können Sie sich als eine Gruppe von Blogbeiträgen vorstellen. Der Code ist jedoch einfacher zu lesen, wenn Sie anstelle des Feed-Schlüssels den Group-Schlüssel verwenden. Wegen der Verwendung des Feed-Schlüssels müssen Sie die Bindung im Seitentitel so ändern, dass eine Bindung an die Feed-Eigenschaft (und nicht an Group) erfolgt. Außerdem umfasst der Titel zwei Spalten, um zu verhindern, dass er abgeschnitten wird.

BR211380.wedge(de-de,WIN.10).gifSo aktualisieren Sie den Seitentitel

  1. Doppelklicken Sie zum Öffnen im Projektmappen-Explorer auf SplitPage.xaml.
  2. Wählen Sie den Grid namens titlePanel aus.
  3. Legen Sie die ColumnSpan-Eigenschaft im Eigenschaftenbereich unter Layout auf "2" fest, und drücken Sie die Eingabetaste.

    Hinweis  Bei Verwendung der Standardbreite für das Eigenschaftenfenster wird die Eigenschaft ColumnSpan wie folgt angezeigt: Colum....

    Das XAML wird wie hier dargestellt aktualisiert.

    
    <!-- Back button and page title -->
    <Grid x:Name="titlePanel" Grid.ColumnSpan="2">
    
    
  4. Wählen Sie das TextBlock-Element namens pageTitle aus.
  5. Klicken Sie im Bereich Eigenschaften unter Allgemein auf den Eigenschaftsmarker für die Text-Eigenschaft. Das Eigenschaftenmenü wird geöffnet.

    Hinweis  Der Text-Eigenschaftenmarker ist orange. Dies gibt an, dass der Marker auf eine Bindung festgelegt wurde.

  6. Wählen Sie im Eigenschaftsmenü die Option Datenbindung erstellen... aus. Das Dialogfeld Datenbindung erstellen wird geöffnet.
  7. Ändern Sie im Dialogfeld Datenbindung erstellen den Wert im Textfeld Pfad in "Feed.Title", und klicken Sie auf OK.

    Das XAML für TextBlock wird folgendermaßen aktualisiert:

    
    <TextBlock x:Name="pageTitle" Grid.Column="1" Text="{Binding Feed.Title}" 
               Style="{StaticResource PageHeaderTextStyle}"/>
    
    
  8. Drücken Sie F5, um die App zu erstellen und auszuführen. Wenn Sie nun auf die geteilte Seite navigieren, wird der Seitentitel angezeigt.

Geteilte Seite mit Standardformaten

Hinzufügen der WebView

Die Details für das ausgewählte Element werden von der Vorlage für die geteilte Seite standardmäßig in einem TextBlock angezeigt. Bei der Zeichenfolge mit dem Beitragsinhalt handelt es sich jedoch nicht um einfachen Text, sondern um eine HTML-Zeichenfolge. Wenn Sie die Zeichenfolge in einem TextBlock anzeigen, sind einige HTML-Tags zu erkennen. Dies ist jedoch nicht gewünscht. Stattdessen verwenden Sie ein WebView-Steuerelement, um HTML anzuzeigen. Außerdem ändern Sie das Layout für den Titel und den Inhalt des ausgewählten Blogbeitrags.

BR211380.wedge(de-de,WIN.10).gifSo fügen Sie die Webansicht hinzu

  1. Löschen Sie in SplitPage.xaml den ScrollViewer namens itemDetail sowie seinen gesamten Inhalt.
  2. Fügen Sie im XAML-Editor dieses XAML anstelle des gelöschten ScrollViewer-Elements itemDetail hinzu.
    
            <!-- Details for selected item -->
            <ScrollViewer
                x:Name="itemDetail"
                AutomationProperties.AutomationId="ItemDetailScrollViewer"
                Grid.Column="1"
                Grid.Row="1"
                Padding="70,0,120,0"
                DataContext="{Binding SelectedItem, ElementName=itemListView}"
                Style="{StaticResource VerticalScrollViewerStyle}">
            
                <Grid x:Name="itemDetailGrid">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="*"/>
                    </Grid.RowDefinitions>
            
                    <TextBlock x:Name="itemTitle" Text="{Binding Title}" 
                               Style="{StaticResource SubheaderTextStyle}"/>
                    <Border x:Name="contentViewBorder" BorderBrush="Gray" BorderThickness="2" 
                            Grid.Row="1" Margin="0,15,0,20">
                        <Grid>
                            <WebView x:Name="contentView" />
                            <Rectangle x:Name="contentViewRect" />
                        </Grid>    
                    </Border>
                </Grid>
            </ScrollViewer>
    
    

Das WebView-Steuerelement ermöglicht es Ihnen, HTML-Daten in der App bereitzustellen. Ein Blick auf dessen Source-Eigenschaft zeigt allerdings, dass ein Uri nötig ist, damit die Webseite angezeigt wird. Ihre HTML-Daten bestehen lediglich aus einer HTML-Zeichenfolge. Es gibt keinen Uri, den Sie an die Source-Eigenschaft binden können. Zum Glück gibt es eine NavigateToString-Methode, an die Sie Ihre HTML-Zeichenfolge übergeben können.

Behandeln Sie alle Fehler, die möglicherweise auftreten, wenn ein WebView-Steuerelement zum Anzeigen von Inhalt verwendet wird, der möglicherweise nicht verfügbar ist.

An dieser Stelle wird das NavigationFailed-Ereignis behandelt, um die Fehlermeldung im WebView-Steuerelement für eine fehlerhafte Navigation anzuzeigen.

BR211380.wedge(de-de,WIN.10).gifSo behandeln Sie Navigationsfehler

  1. Öffnen Sie das im vorherigen Schritt erstellte WebView-Element contentView.
  2. Klicken Sie im Eigenschaftenfenster auf die Ereignisschaltfläche (Ereignisschaltfläche).
  3. Suchen Sie in der Ereignisliste das NavigationFailed-Ereignis. Geben Sie im Textfeld für das Ereignis "ContentView_NavigationFailed" als Namen der Methode ein, die das NavigationFailed-Ereignis behandelt.
  4. Drücken Sie die EINGABETASTE. Die Ereignishandlermethode wird erstellt und im Code-Editor geöffnet, damit Sie den Code hinzufügen können, der bei Auftreten des Ereignisses ausgeführt werden soll.
  5. Fügen Sie diesen Code dem ContentView_NavigationFailed-Ereignishandler auf der CodeBehind-Seite hinzu.
    
                string errorString = "<p>Page could not be loaded.</p><p>Error is: " + e.WebErrorStatus.ToString() + "</p>";
                this.contentView.NavigateToString(errorString);
    
    

Um die WebView zu füllen, fügen Sie Ihren Code dem Ereignishandler ItemListView_SelectionChanged hinzu. Im Ereignishandler wandeln Sie das ausgewählte Element in ein FeedItem um und rufen die HTML-Zeichenfolge aus der Content-Eigenschaft ab. Dann übergeben Sie die Zeichenfolge an die NavigateToString-Methode. Wenn kein Element ausgewählt wird, leeren Sie die WebView durch Übergabe einer leeren Zeichenfolge.

BR211380.wedge(de-de,WIN.10).gifSo füllen Sie die Webansicht

  1. Doppelklicken Sie im Projektmappen-Explorer auf SplitPage.xaml.cs/vb. Die Datei wird im Code-Editor geöffnet.
  2. Fügen Sie diesen Code am Ende der ItemListView_SelectionChanged-Methode hinzu, um die WebView mit dem Inhalt des ausgewählten Blogbeitrags zu füllen.

    Hinweis  Erweitern Sie den Bereich für die logische Seitennavigation, damit die ItemListView_SelectionChanged-Methode angezeigt wird.

    
    
                // Add this code to populate the web view
                //  with the content of the selected blog post.
                Selector list = sender as Selector;
                FeedItem selectedItem = list.SelectedItem as FeedItem;
                if (selectedItem != null)
                {
                    this.contentView.NavigateToString(selectedItem.Content);
                }
                else
                {
                    this.contentView.NavigateToString("");
                }      
    
    
    
  3. Drücken Sie F5, um die App zu erstellen und auszuführen.

Die geteilte Seite sieht jetzt besser aus. Der ausgewählte Blogbeitrag wird in einem besser lesbaren Format dargestellt.

Geteilte Seite mit Standardformaten

Laden der DetailPage

Nun fügen Sie der Detailseite Inhalte hinzu. In DetailPage.xaml müssen Sie den TextBlock des Titels an den Titel des Blogbeitrags binden und ein WebView-Steuerelement zum Anzeigen der Blogseite hinzufügen.

BR211380.wedge(de-de,WIN.10).gifSo aktualisieren Sie die Detailseite

  1. Doppelklicken Sie zum Öffnen im Projektmappen-Explorer auf DetailPage.xaml.
  2. Binden Sie den TextBlock des Seitentitels an die Title-Eigenschaft des ausgewählten Blogbeitrags.
    1. Wählen Sie den TextBlock mit dem Namen pageTitle aus.
    2. Klicken Sie im Fenster Eigenschaften auf die Schaltfläche "Eigenschaften" (Ereignisschaltfläche).
    3. Klicken Sie im Eigenschaftenpanel unter Allgemein auf den Eigenschaftenmarker für die Text-Eigenschaft. Das Eigenschaftenmenü wird geöffnet.
    4. Wählen Sie im Eigenschaftenmenü Datenbindung erstellen aus. Das Dialogfeld Datenbindung erstellen wird geöffnet.
    5. Wählen Sie im Dialogfeld Datenbindung erstellen in der Dropdownliste Bindungstyp die Option Datenkontext aus.
    6. Geben Sie im Textfeld "Pfad" einen Titel ein, und klicken Sie dann auf OK.

      Hinweis  Im Dialogfeld Datenbindung erstellen wird eine Meldung angezeigt, dass der Datenkontext nicht festgelegt ist. Das ist in Ordnung, da Sie den Datenkontext im Code festlegen, wenn Sie die App ausführen.

  3. Fügen Sie im XAML-Editor dieses XAML nach dem Grid mit dem Seitentitel und vor dem Abschnitt VisualStateManager.VisualStateGroups hinzu.
    
    
            <Border x:Name="contentViewBorder" BorderBrush="Gray" BorderThickness="2" 
                    Grid.Row="1" Margin="120,15,20,20">
                <WebView x:Name="contentView" 
                         NavigationFailed="ContentView_NavigationFailed"/>
            </Border>
    
    
  4. Doppelklicken Sie zum Öffnen im Projektmappen-Explorer auf DetailPage.xaml.cs/vb.
  5. Fügen Sie diesen Code der Überschreibung der LoadState-Methode hinzu.

    Dieser Code navigiert die WebView zum Uniform Resource Identifier (URI) des Blogbeitrags und legt den DataContext der Seite fest.

    
    
                // Add this code to navigate the web view to the selected blog post.
                string itemTitle = (string)navigationParameter;
                FeedItem feedItem = FeedDataSource.GetItem(itemTitle);
                if (feedItem != null)
                {
                    this.contentView.Navigate(feedItem.Link);
                    this.DataContext = feedItem;
                }
    
    
    
  6. Fügen Sie diesen Code der DetailPage-Klasse hinzu, um das WebView.NavigationFailed-Ereignis zu behandeln.
    
            private void ContentView_NavigationFailed(object sender, WebViewNavigationFailedEventArgs e)
            {
                string errorString = "<p>Page could not be loaded.</p><p>Error is: " + e.WebErrorStatus.ToString() + "</p>";
                this.contentView.NavigateToString(errorString);
            }
    
    
  7. Drücken Sie F5, um die App zu erstellen und auszuführen.

    Alle Daten sind jetzt eingebunden. Es gibt jedoch noch keine Möglichkeit, zur erstellten Detailseite zu navigieren. Im nächsten Schritt widmen Sie sich der Navigation zur Detailseite.

Hinzufügen von App-Leisten

Der Großteil der Navigation in der Blogleser-App findet statt, wenn der Benutzer ein Element auf der Benutzeroberfläche auswählt. Auf der geteilten Seite müssen Sie es dem Benutzer jedoch ermöglichen, zur Detailansicht des Blogbeitrags zu wechseln. Sie könnten eine Schaltfläche auf der Seite platzieren. Aber das würde vom eigentlichen Zweck der App, dem Lesen, nur ablenken. Stattdessen platzieren Sie die Schaltfläche auf einer App-Leiste, die erst angezeigt wird, wenn der Benutzer sie benötigt.

Die App-Leiste ist ein Teil der UI und standardmäßig ausgeblendet. Sie wird ein- oder ausgeblendet, wenn der Benutzer den Finger über den Bildschirmrand zieht oder mit der App interagiert. Auf der App-Leiste findet der Benutzer Navigationsfunktionen, Befehle und Tools. Eine App-Leiste kann am oberen Seitenrand, am unteren Seitenrand oder sowohl oben als auch unten angezeigt werden. Wir empfehlen Ihnen, die Navigation in der oberen App-Leiste zu platzieren und Tools und Befehle in der unteren. Mit den Eigenschaften IsSticky und IsOpen können Sie steuern, wie und wann die App-Leiste ein- und ausgeblendet wird. Mit den Ereignissen Opened und Closed können wir außerdem auf das Öffnen oder Ausblenden der App-Leiste reagieren.

Um eine App-Leiste in XAML hinzuzufügen, weisen Sie der TopAppBar- oder BottomAppBar-Eigenschaft einer Page ein AppBar-Steuerelement zu. Der oberen App-Leiste fügen Sie eine Schaltfläche hinzu, mit der zur Detailseite gewechselt werden kann. Die Datei StandardStyles.xaml enthält verschiedene allgemeine Schaltflächenstile für die App-Leiste. Diese Stile dienen Ihnen bei der Erstellung eines Stils für Ihre Schaltfläche als Orientierungshilfe. Sie platzieren Ihren Stil im Abschnitt Page.Resources von SplitPage.xaml und fügen direkt hinter den Ressourcenabschnitt das Page.TopAppBar-XAML ein:

BR211380.wedge(de-de,WIN.10).gifSo fügen Sie eine App-Leiste hinzu

  1. Doppelklicken Sie zum Öffnen im Projektmappen-Explorer auf SplitPage.xaml.
  2. Fügen Sie im XAML-Editor dieses XAML im Abschnitt Page.Resources im oberen Bereich der Seite hinzu.

    Dadurch wird die Style-Ressource für die Schaltfläche der App hinzugefügt. Auf das Thema Formate gehen wir später im Abschnitt Erzielen eines einheitlichen Aussehens mit Stilen noch genauer ein.

    
    
        <Style x:Key="WebViewAppBarButtonStyle" TargetType="Button" 
               BasedOn="{StaticResource AppBarButtonStyle}">
            <Setter Property="AutomationProperties.AutomationId" Value="WebViewAppBarButton"/>
            <Setter Property="AutomationProperties.Name" Value="View Web Page"/>
            <Setter Property="Content" Value="&#xE12B;"/>
        </Style>
    
    
    
  3. Fügen Sie dieses XAML nach dem Abschnitt Page.Resources der Seite hinzu.

    Dadurch wird der TopAppBar-Eigenschaft der Seite ein AppBar-Steuerelement hinzugefügt.

    
    <Page.TopAppBar>
       <AppBar Padding="10,0,10,0">
            <Grid>
    
                <Button HorizontalAlignment="Right" 
                        Style="{StaticResource WebViewAppBarButtonStyle}"/>
            </Grid>
        </AppBar>
    </Page.TopAppBar>
    
    
  4. Wählen Sie in der App-Leiste die soeben hinzugefügte Button aus.
  5. Klicken Sie im Eigenschaftenfenster auf die Ereignisschaltfläche (Ereignisschaltfläche).
  6. Suchen Sie am Anfang der Ereignisliste nach dem Click-Ereignis. Geben Sie im Textfeld für das Ereignis "ViewDetail_Click" als Namen der Methode ein, die das Click-Ereignis behandelt.
  7. Drücken Sie die EINGABETASTE. Die Ereignishandlermethode wird erstellt und im Code-Editor geöffnet, damit Sie den Code hinzufügen können, der bei Auftreten des Ereignisses ausgeführt werden soll.
  8. Fügen Sie diesen Code der Ereignishandlermethode hinzu, um die Navigation für die Detailseite zu behandeln.
    
    
                FeedItem selectedItem = this.itemListView.SelectedItem as FeedItem;
                if (selectedItem != null && this.Frame != null)
                {
                    string itemTitle = selectedItem.Title;
                    this.Frame.Navigate(typeof(DetailPage), itemTitle);
                }
    
    
    
  9. Drücken Sie F5, um die App zu erstellen und auszuführen. Klicken Sie auf einen Blogbeitrag, um zur geteilten Seite zu navigieren, und wählen Sie einen Blogbeitrag aus. Klicken Sie mit der rechten Maustaste auf den Seitenheader, um die App-Leiste anzuzeigen, und klicken Sie anschließend auf die Schaltfläche Show Web View, um zur Detailseite zu navigieren.

Hinzufügen von Animationen und Übergängen

Bei Animationen fallen uns meist zuerst irgendwelche Objekte ein, die auf dem Bildschirm herumhüpfen. Im XAML ist eine Animation im Wesentlichen ein Verfahren, um den Wert einer Eigenschaft für ein Objekt zu ändern. Damit eignen sich Animationen für viel mehr als nur für hopsende Bälle. In der Blogleser-App passen Sie die UI mit Animationen an verschiedene Layouts und Ausrichtungen an. Im nächsten Abschnitt gehen wir genauer darauf ein. Zunächst wird jedoch erläutert, wie Animationen eigentlich funktionieren.

Dazu platzieren Sie eine Animation in einem Storyboard. Wenn das Storyboard ausgeführt wird, ändert sich die Eigenschaft, wie von der Animation angegeben. Ein Storyboard kann eine oder viele Animationen enthalten. Jede Animation gibt ein Zielobjekt, eine für das Objekt zu ändernde Eigenschaft und einen neuen Wert für die Eigenschaft an.

Die Blogleser-App enthält eine ListView mit dem Namen itemListView. Die folgende Animation ändert die Visibility-Eigenschaft von itemListView in Visible, wenn das Storyboardausgeführt wird.


<Storyboard>
    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemListView" 
                                   Storyboard.TargetProperty="Visibility" >
        <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
    </ObjectAnimationUsingKeyFrames>
</Storyboard>


Hinzufügen von Designanimationen

Führen Sie die App erneut aus, und beachten Sie, wie sanft die UI-Elemente beim Laden einer Seite auf den Bildschirm gleiten. Abgesehen von dem hinzugefügten WebView-Steuerelement. Dieses wird einfach so angezeigt. Windows 8 verwendet Animationen und Übergänge, um die Benutzeroberfläche zu optimieren. Sie möchten, dass Ihre App die gleichen Vorzüge aufweist wie Windows 8. Erfreulicherweise können Sie die integrierten Designanimationen und Designübergänge verwenden, sodass Ihre App mit Windows 8 harmoniert. Diese Animationen und Übergänge befinden sich im Windows.UI.Xaml.Media.Animation-Namespace.

Eine Designanimation ist vorkonfiguriert und kann in einem Storyboard platziert werden. Bei der PopInThemeAnimation wird die Webansicht beim Laden der Seite von rechts nach links eingeschoben. Ein höherer Wert der FromHorizontalOffset-Eigenschaft verstärkt diesen Effekt noch. Sie platzieren hier die PopInThemeAnimation in einem Storyboard und machen sie zu einer Ressource in DetailPage.xaml. Legen Sie das Ziel der Animation auf den Border fest, der Ihren Webinhalt umgibt. Dadurch wird der Border und sein gesamter Inhalt animiert.

BR211380.wedge(de-de,WIN.10).gifSo fügen Sie eine Designressource hinzu

  1. Doppelklicken Sie zum Öffnen im Projektmappen-Explorer auf DetailPage.xaml.
  2. Fügen Sie im XAML-Editor dieses XAML dem Abschnitt Page.Resources hinzu.
    
    
        <Storyboard x:Name="PopInStoryboard">
            <PopInThemeAnimation  Storyboard.TargetName="contentViewBorder" 
                                  FromHorizontalOffset="400"/>
        </Storyboard>
    
    
    

Auf der CodeBehind-Seite beginnen Sie das Storyboard in der LoadState-Methode. Die Einblendanimation wird dann auf den Border angewendet, wenn der Benutzer zur Detailseite wechselt.

BR211380.wedge(de-de,WIN.10).gifSo starten Sie das Storyboard für Animationen

  1. Doppelklicken Sie zum Öffnen im Projektmappen-Explorer auf DetailPage.xaml.cs/vb.
  2. Fügen Sie diesen Code am Anfang der LoadState-Methode hinzu.
    
    
                // Run the PopInThemeAnimation 
                Windows.UI.Xaml.Media.Animation.Storyboard sb =
                    this.FindName("PopInStoryboard") as Windows.UI.Xaml.Media.Animation.Storyboard;
                if (sb != null) sb.Begin();
    
    
    
  3. Drücken Sie F5, um die App zu erstellen und auszuführen. Navigieren Sie zur Detailseite. Nun gleitet das WebView-Steuerelement zusammen mit den anderen UI-Elementen auf den Bildschirm, wenn die geteilte Seite geladen wird.

Hier sehen Sie den aktualisierten Code für die LoadState-Methode.


        protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
        {
            // Run the PopInThemeAnimation 
            Windows.UI.Xaml.Media.Animation.Storyboard sb =
                this.FindName("PopInStoryboard") as Windows.UI.Xaml.Media.Animation.Storyboard;
            if (sb != null) sb.Begin();

            // Add this code to navigate the web view to the selected blog post.
            string itemTitle = (string)navigationParameter;
            FeedItem feedItem = FeedDataSource.GetItem(itemTitle);
            if (feedItem != null)
            {
                this.contentView.Navigate(feedItem.Link);
                this.DataContext = feedItem;
            }
        }

Sie können auch diese Schritte ausführen und denselben Code verwenden, um diese Animation dem contentViewBorder-Element in der SplitPage hinzuzufügen.

Weitere Informationen und eine vollständige Liste der Designanimationen und -übergänge finden Sie unter Schnellstart: Animieren der Benutzeroberfläche anhand von Bibliotheksanimationen.

Erzielen eines einheitlichen Aussehens mit Stilen

Sie möchten, dass das Erscheinungsbild Ihrer Blogleser-App mit der Website mit den Windows-Teamblogs harmoniert. Den Benutzern soll der Wechsel zwischen der Website und Ihrer App nicht auffallen. Das dunkle Standarddesign für das Projekt passt jedoch nicht allzu gut zur Website mit den Windows-Teamblogs. Das sticht vor allem hier auf der Detailseite ins Auge, auf der Sie die eigentliche Blogseite in eine WebView laden, wie hier dargestellt:

Detailseite mit dunklem Design

Um der App ein einheitliches Erscheinungsbild zu verleihen, das Sie bei Bedarf aktualisieren können, verwenden Sie Brush-Elemente und Stile. Mit einem Brush können Sie an einer Stelle eine Darstellungsweise definieren und sie beliebig weiterverwenden. Mit einem Style können Sie Werte für die Eigenschaften eines Steuerelements festlegen und diese Einstellungen in der gesamten App wiederverwenden.

Bevor wir uns aber weiter mit den Details beschäftigen, erklären wir kurz, wie Sie mithilfe eines Brush-Elements die Hintergrundfarbe der Seiten in Ihrer App festlegen können. Jede Seite in Ihrer App hat ein Grid-Stammelement. Für dieses Element ist eine Background-Eigenschaft festgelegt, mit der die Hintergrundfarbe der Seite definiert wird. Sie könnten nun die Hintergrundfarbe der Seiten einzeln festlegen, wie hier dargestellt.


<Grid Background="Blue">

Besser wäre jedoch, einen Brush als Ressource zu definieren und damit die Hintergrundfarbe aller Seiten festzulegen. Sie definieren Objekte und Werte als Ressourcen, um sie wiederverwendbar zu machen. Wenn Sie ein Objekt oder einen Wert als Ressource verwenden möchten, müssen Sie dessen x:Key-Attribut festlegen. Mit diesem Schlüssel verweisen Sie in Ihrem XAML auf die Ressource. Hier wird der Hintergrund auf eine Ressource mit dem Schlüssel ApplicationPageBackgroundThemeBrush festgelegt. Dabei handelt es sich um ein vom System definiertes SolidColorBrush-Element.


<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">

Das ist in Ordnung, um die Background-Eigenschaft des Grid festzulegen, meistens müssen jedoch mehrere Eigenschaften festgelegt werden, um die gewünschte Optik zu erzielen. Sie können Einstellungen für eine beliebige Anzahl von Eigenschaften als Style gruppieren und den Style auf ein Steuerelement anwenden.

Sie können Ressourcen in der XAML-Datei einer bestimmten Seite, in der Datei App.xaml oder in einer separaten XAML-Datei mit Ressourcenverzeichnis (beispielsweise StandardStyles.xaml) definieren. Der Ort, an dem Sie die Ressource definieren, bestimmt den Bereich, in dem sie verwendet werden kann. Visual Studio erstellt die Datei StandardStyles.xaml als Teil der Projektvorlage und platziert sie im Ordner Common. Dabei handelt es sich um ein Ressourcenverzeichnis mit den Werten, Stilen und Datenvorlagen, die in den Seitenvorlagen von Visual Studio verwendet werden. Eine XAML-Datei des Ressourcenverzeichnisses kann App-übergreifend genutzt werden. Außerdem können in einer einzelnen App mehrere Ressourcenverzeichnisse zusammengeführt werden.

In der Blogleser-App definieren Sie Ressourcen in App.xaml, um sie für die gesamte App verfügbar zu machen. Und Sie haben einige Ressourcen in der XAML-Datei für einzelne Seiten definiert. Diese Ressourcen sind nur auf der Seite verfügbar, für die sie definiert sind. Sind Ressourcen mit demselben Schlüssel in App.xaml und auf einer Seite definiert, haben die Ressourcen der Seite Vorrang vor den Ressourcen in App.xaml. Analog dazu hat eine Ressource in App.xaml Vorrang vor einer Ressource, die in einer separaten Ressourcenverzeichnisdatei mit dem gleichen Schlüssel definiert ist. Weitere Informationen finden Sie unter Schnellstart: Formatieren von Steuerelementen.

Sehen wir uns nun ein Anwendungsbeispiel für Styles in der App an. Die Darstellung der Vorlagenseiten wird durch einen Stil mit dem Schlüssel LayoutRootStyle definiert. Die Style-Definition befindet sich in der Datei StandardStyles.xaml.


<Grid Style="{StaticResource LayoutRootStyle}">



    <!-- Page layout roots typically use entrance animations  
         and a theme-appropriate background color -->

    <Style x:Key="LayoutRootStyle" TargetType="Panel">
        <Setter Property="Background" 
                Value="{StaticResource ApplicationPageBackgroundThemeBrush}"/>
        <Setter Property="ChildrenTransitions">
            <Setter.Value>
                <TransitionCollection>
                    <EntranceThemeTransition/>
                </TransitionCollection>
            </Setter.Value>
        </Setter>
    </Style>

In der Style-Definition benötigen Sie ein TargetType-Attribut und eine Auflistung eines oder mehrerer Setter. Sie legen den TargetType auf eine Zeichenfolge fest, die den Typ angibt, auf den der Style angewendet wird (in diesem Fall: Panel). Wenn Sie versuchen, einen Style auf ein Steuerelement anzuwenden, das nicht zum TargetType-Attribut passt, wird eine Ausnahme ausgelöst. Jedes Setter-Element benötigt eine Property und einen Value. Diese Eigenschaftseinstellungen geben die Steuerelementeigenschaft an, auf die die Einstellung angewendet wird, und den Wert, der für diese Eigenschaft festgelegt wird.

Um den Background Ihrer Seiten zu ändern, müssen Sie den ApplicationPageBackgroundThemeBrush durch ein benutzerdefiniertes Brush-Element ersetzen. Für Ihr benutzerdefiniertes Brush-Element legen wir als Color den Wert "#FF0A2562" fest – ein schönes Blau, das wunderbar zu den Farben der Website unter "http://windowsteamblog.com" passt. Um das Brush-Element für das Systemdesign zu ersetzen, erstellen Sie einen neuen Style auf der Grundlage von LayoutRootStyle und ändern dort die Background-Eigenschaft. Hier definieren Sie einen neuen Stil für den Layoutstamm.

BR211380.wedge(de-de,WIN.10).gifSo ändern Sie den Seitenhintergrund

  1. Doppelklicken Sie zum Öffnen im Projektmappen-Explorer auf App.xaml.
  2. Fügen Sie im XAML-Editor diese Brush- und Stildefinitionen im ResourceDictionary mit den App-spezifischen Ressourcen nach der feedDataSource-Ressource hinzu.
    
    
                <SolidColorBrush x:Key="WindowsBlogBackgroundBrush" 
                                        Color="#FF0A2562"/>
                <Style x:Key="WindowsBlogLayoutRootStyle" 
                               TargetType="Panel" 
                               BasedOn="{StaticResource LayoutRootStyle}">
                    <Setter Property="Background" 
                                    Value="{StaticResource WindowsBlogBackgroundBrush}"/>
                </Style>
    
    

Hier sehen Sie das vollständige XAML für den Abschnitt ResourceDictionary von App.xaml.


    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>

                <!-- 
                    Styles that define common aspects of the platform look and feel
                    Required by Visual Studio project and item templates
                 -->
                <ResourceDictionary Source="Common/StandardStyles.xaml"/>
            </ResourceDictionary.MergedDictionaries>

            <local:FeedDataSource x:Key="feedDataSource"/>

            <SolidColorBrush x:Key="WindowsBlogBackgroundBrush" 
                                    Color="#FF0A2562"/>
            <Style x:Key="WindowsBlogLayoutRootStyle" 
                           TargetType="Panel" 
                           BasedOn="{StaticResource LayoutRootStyle}">
                <Setter Property="Background" 
                                Value="{StaticResource WindowsBlogBackgroundBrush}"/>
            </Style>
        </ResourceDictionary>
    </Application.Resources>

Wichtig  Da Sie in StandardStyles.xaml einen Stil auf Grundlage eines Systemstils erstellt haben, muss das ResourceDictionary-Element, das StandardStyles.xaml enthält, im XAML vor Ihrem Stil deklariert werden, der darauf basiert. Andernfalls kann der XAML-Parser den LayoutRootStyle nicht finden, auf dem Ihr Stil basiert.

Die Zeile BasedOn="{StaticResource LayoutRootStyle}" gibt an, dass Ihr neuer Style alle nicht ausdrücklich festgelegten Eigenschaften von LayoutRootStyle erbt. Mit Ausnahme des blauen Hintergrunds entspricht Ihr neuer Style dem Standardstil und kann für alle Seiten verwendet werden.

BR211380.wedge(de-de,WIN.10).gifSo ändern Sie den Hintergrund der einzelnen Seiten

  1. Doppelklicken Sie zum Öffnen im Projektmappen-Explorer auf ItemsPage.xaml.
  2. Wählen Sie das Grid für das Stammlayout der Seite aus.
  3. Suchen Sie unter Sonstiges im Eigenschaftenpanel die Style-Eigenschaft.
  4. Klicken Sie auf den Eigenschaftsmarker neben der Style-Eigenschaft, um das Menü zu öffnen.
  5. Klicken Sie im Menü auf Lokale Ressource > WindowsBlogLayoutRootStyle.
  6. Wiederholen Sie die Schritte 2 bis 5 für SplitPage.xaml und DetailPage.xaml.

    Das XAML für das Grid-Stammelement auf den einzelnen Seiten sieht nun wie folgt aus.

    
    
     <Grid Style="{StaticResource WindowsBlogLayoutRootStyle}">
    
    
  7. Drücken Sie F5, um die App zu erstellen und auszuführen, und sehen Sie sich die blauen Seiten an.

Mit benutzerdefinierten Datenvorlagen sowie mit Brush- und Style-Elementen erhält die App das gleiche Erscheinungsbild wie die Website mit den Windows-Teamblogs. Verwenden Sie für den Anfang Vorlagen zum Formatieren der Listenelemente auf der geteilten Seite.

Formatieren von Daten mit einer Datenvorlage

In SplitPage.xaml wird die Darstellung der Elemente in "itemListView" in der "Standard130ItemTemplate" definiert, die sich in StandardStyles.xaml befindet. Die Elementvorlage wird in dieser Zeile des XAML-Codes zugewiesen: ItemTemplate="{StaticResource Standard130ItemTemplate}". Um die Auswirkung der Vorlage anzuzeigen, können Sie diese entfernen und somit sehen, wie die Liste ohne die Vorlage aussieht.

Eine gebundene Liste mit den Titeln

Sie haben die ListView an die Items-Eigenschaft des FeedData-Objekts gebunden. Die richtigen Daten sind also vorhanden. Wenn Sie die App aber so ausführen, ist für die ListView nicht klar, was angezeigt werden soll. Sie ruft also nur ToString für das Objekt auf, an das sie gebunden ist. Damit erhalten Sie eine Liste mit WindowsBlogReader.FeedItem-Zeichenfolgen wie die zuvor gesehenen. Das ist natürlich nicht das, was Sie zeigen möchten.

Sie können das etwas verbessern, indem Sie die DisplayMemberPath-Eigenschaft für die ListView festlegen. Dadurch erkennt die Listenansicht, dass ToString für die angegebene Eigenschaft des gebundenen Objekts und nicht direkt für das gebundene Objekt aufgerufen werden muss. Wenn Sie DisplayMemberPath=Title festlegen, zeigt die ListView eine Liste mit Titeln von Blogbeiträgen.

Hier sehen Sie das ListView-XAML, bei dem das DisplayMemberPath-Element auf die Title-Eigenschaft festgelegt ist.


<ListView
    x:Name="itemListView"
    AutomationProperties.AutomationId="ItemsListView"
    AutomationProperties.Name="Items"
    TabIndex="1"
    Grid.Row="1"
    Margin="-10,-10,0,0"
    Padding="120,0,0,60"
    ItemsSource="{Binding Source={StaticResource itemsViewSource}}"
    IsSwipeEnabled="False"
    SelectionChanged="ItemListView_SelectionChanged"
    DisplayMemberPath="Title"/>

Wenn Sie die App ausführen, werden die Listenelemente folgendermaßen dargestellt. Damit kommen Sie der Sache schon näher.

Eine gebundene Liste mit den Titeln

Aber eigentlich möchten Sie Titel, Autor und Veröffentlichungsdatum für jeden Beitrag in der Liste anzeigen. Um mehrere Eigenschaften des Datenelements anzuzeigen, definieren Sie eine Vorlage, die das ListView-Element genau anweist, wie die Daten dargestellt werden sollen. Die Steuerelemente zum Anzeigen der Auflistungen mit Datenelementen werden von der ItemsControl-Klasse abgeleitet. Diese Steuerelemente besitzen eine ItemTemplate-Eigenschaft, die Sie einer DataTemplate zuweisen können. Die DataTemplate definiert die Darstellung Ihrer Daten.

Wichtig  Sie können die DisplayMemberPath-Eigenschaft und die ItemTemplate-Eigenschaft nicht gleichzeitig verwenden. Wenn Sie die ItemTemplate-Eigenschaft festlegen, müssen Sie unbedingt die DisplayMemberPath-Einstellung entfernen.

Die Standardelementvorlage kommt dem, was Sie zeigen möchten, nahe. Verwenden Sie sie also als Ausgangspunkt für Ihre Vorlage.

BR211380.wedge(de-de,WIN.10).gifSo erstellen Sie eine neue Elementvorlage (ItemTemplate)

  1. Öffnen Sie im Projektmappen-Explorer die Datei SplitPage.xaml.
  2. Wählen Sie das ListView-Element namens "itemListView" aus.
  3. Klicken Sie im Eigenschaftenpanel unter Sonstiges auf den Eigenschaftsmarker für die ItemTemplate-Eigenschaft. Das Eigenschaftenmenü wird geöffnet.

    Hinweis  Der Eigenschaftsmarker ist das kleine Feldsymbol rechts vom jeweiligen Eigenschaftswert. Der ItemTemplate-Eigenschaftenmarker ist grün. Dies gibt an, dass der Marker auf eine Ressource festgelegt wurde.

  4. Wählen Sie im Eigenschaftenmenü die Option In neue Ressource konvertieren... aus. Das Dialogfeld zum Erstellen von Datenvorlagenressourcen wird geöffnet.
  5. Geben Sie im Dialogfeld zum Erstellen von Datenvorlagenressourcen "DefaultListItemTemplate" in das Textfeld Name (Schlüssel) ein.

    Stellen Sie sicher, dass für die Einstellung Definieren in die Option Dieses Dokument > "LayoutAwarePage:pageRoot" festgelegt ist.

    Hinweis  Die XAML-Seite Entwurfsansicht muss in Visual Studio angezeigt werden. Wird nur der XAML-Editor angezeigt, sind einige Optionen deaktiviert.

  6. Klicken Sie auf OK.

    Eine neue DataTemplate wird im Abschnitt Resources der Datei SplitPage.xaml erstellt. Dabei handelt es sich um eine Kopie der Standard130ItemTemplate-Ressource, die angepasst werden kann. Die ItemTemplate-Eigenschaft von itemListView wird ebenfalls zur Verwendung von DefaultListItemTemplate aktualisiert.

Das Fragment der UI innerhalb der DataTemplate wird genau so definiert wie jede andere UI. Diese Vorlage enthält ein Raster mit zwei Spalten. Die erste Spalte hat einen rechteckigen Rahmen mit einem Platzhalterbild. Die zweite Spalte hat ein StackPanel-Element mit drei übereinander angeordneten TextBlock-Elementen. Standardmäßig werden die Text-Eigenschaften der TextBlock-Elemente an Eigenschaften der Beispieldatenquelle gebunden, die in den Visual Studio-Vorlagen verwendet wird. Der standardmäßige DataContext für diese Bindungen ist das Objekt, das in der ListView angezeigt wird: ein FeedItem. Sie können die Bindungen also aktualisieren, sodass sie die Eigenschaften Title, Author und PubDate von FeedItem anzeigen.

Hier sehen Sie das XAML für die Datenvorlage mit den aktualisierten Bindungen.


        <DataTemplate x:Key="DefaultListItemTemplate">
            <Grid Height="110" Margin="6">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}" 
                        Width="110" Height="110">
                    <Image Source="{Binding Image}" Stretch="UniformToFill" 
                           AutomationProperties.Name="{Binding Title}"/>
                </Border>
                <StackPanel Grid.Column="1" VerticalAlignment="Top" Margin="10,0,0,0">
                    <TextBlock Text="{Binding Title}" 
                               Style="{StaticResource TitleTextStyle}" TextWrapping="NoWrap"/>
                    <TextBlock Text="{Binding Author}" 
																															Style="{StaticResource CaptionTextStyle}" TextWrapping="NoWrap"/>
                    <TextBlock Text="{Binding PubDate}" 
																															Style="{StaticResource BodyTextStyle}" MaxHeight="60"/>
                </StackPanel>
            </Grid>
        </DataTemplate>

Und so sieht die Liste beim Ausführen der App aus.

Eine gebundene Liste mit einer Datenvorlage

In der Liste werden nun die gewünschten Daten angezeigt, sie beinhaltet jedoch nicht das Branding der Website mit Windows-Teamblogs, wie Sie hier sehen können.

Auflistung der Windows-Blogbeiträge

Damit die Liste mehr der Website ähnelt, verwenden Sie die Elemente ContentControl und ControlTemplate, um das Datum in einem grünen Feld anzuzeigen. Aktualisieren Sie außerdem die Darstellung des TextBlock des Titels, um die Titel in orange anzuzeigen. Darüber hinaus verwenden Sie einen Wertkonverter, um das Datum wie gewünscht zu formatieren.

Formatieren von Daten mit einem Wertkonverter

In der DataTemplate von ItemListView binden Sie die PubDate-Eigenschaft vom Typ DateTime an eine TextBlock.Text-Eigenschaft. Das Bindungsmodul konvertiert PubDate automatisch von DateTime in eine Zeichenfolge. Bei der automatischen Konvertierung werden jedoch sowohl das Datum als auch die Uhrzeit angezeigt. Sie möchten aber nur das Datum anzeigen. Zu diesem Zweck können Sie Ihren eigenen Wertkonverter erstellen, der einen DateTime-Typ in eine Zeichenfolge konvertiert. Zudem können Sie damit die Zeichenfolge ganz nach Wunsch formatieren.

Um einen Wertkonverter zu erhalten, erstellen Sie eine Klasse, die die IValueConverter-Schnittstelle implementiert. Anschließend implementieren Sie die Methoden Convert und ConvertBack. Konverter können Datentypen tauschen, Daten anhand kultureller Informationen übersetzen oder andere Aspekte der Präsentation ändern.

Mit den Methoden Convert und ConvertBack können Sie auch einen Parameter übergeben, sodass Sie dieselbe Konverterinstanz mit verschiedenen Optionen verwenden können. Im vorliegenden Beispiel erzeugt Ihr Formatierungskonverter anhand der Eingabeparameter verschiedene Datumsformate. Mit dem ConverterParameter der Binding-Klasse können Sie einen Parameter als Argument an die Methoden Convert und ConvertBack übergeben. Mit diesem Feature formatieren Sie das Datum so, dass es in dem auf der Blog-Website verwendeten Blockformat angezeigt wird.

Sie erstellen hier einen Konverter, der den übergebenen Datumswert konvertiert und so formatiert, dass er nur Tag, Monat und Jahr wiedergibt.

BR211380.wedge(de-de,WIN.10).gifSo fügen Sie einen Wertkonverter hinzu

  1. Wählen Sie Projekt > Klasse hinzufügen aus. Das Dialogfeld Neues Element wird geöffnet.
  2. Geben Sie DateConverter als Name der Klassendatei ein.
  3. Klicken Sie auf Hinzufügen. Die Klassendatei DateConverter.cs/vb wird erstellt.
  4. Kopieren Sie diesen Code in die Datei DateConverter.cs/vb. Ersetzen Sie den gesamten Code in der Datei.
    
    
    using System;
    using Windows.Globalization.DateTimeFormatting;
    
    namespace WindowsBlogReader
    {
        public class DateConverter : Windows.UI.Xaml.Data.IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, string culture)
            {
                if (value == null)
                    throw new ArgumentNullException("value", "Value cannot be null.");
    
                if (!typeof(DateTime).Equals(value.GetType()))
                    throw new ArgumentException("Value must be of type DateTime.", "value");
                
                DateTime dt = (DateTime)value;
    
                if (parameter == null)
                {
                    // Date "7/27/2011 9:30:59 AM" returns "7/27/2011"
                    return DateTimeFormatter.ShortDate.Format(dt);
                }           
                else if ((string)parameter == "day")
                {
                    // Date "7/27/2011 9:30:59 AM" returns "27"
                    DateTimeFormatter dateFormatter = new DateTimeFormatter("{day.integer(2)}");
                    return dateFormatter.Format(dt);
                }
                else if ((string)parameter == "month")
                {
                    // Date "7/27/2011 9:30:59 AM" returns "JUL"
                    DateTimeFormatter dateFormatter = new DateTimeFormatter("{month.abbreviated(3)}");
                    return dateFormatter.Format(dt).ToUpper();
                }
                else if ((string)parameter == "year")
                {
                    // Date "7/27/2011 9:30:59 AM" returns "2011"
                    DateTimeFormatter dateFormatter = new DateTimeFormatter("{year.full}");
                    return dateFormatter.Format(dt);
                }
                else
                {
                    // Requested format is unknown. Return in the original format.
                    return dt.ToString();
                }
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, string culture)
            {
                string strValue = value as string;
                DateTime resultDateTime;
                if (DateTime.TryParse(strValue, out resultDateTime))
                {
                    return resultDateTime;
                }
                return Windows.UI.Xaml.DependencyProperty.UnsetValue;
            }
        }
    }
    
    
    
  5. Klicken Sie auf Erstellen > Projektmappe erstellen, damit die Projektmappe ohne Fehler erstellt wird.

Bevor Sie die DateConverter-Klasse verwenden können, müssen Sie eine Instanz dieser Klasse in Ihrem XAML deklarieren. Sie deklarieren Sie als App-Ressource mit dem Schlüssel dateConverter in App.xaml. Indem Sie die Instanz an dieser Stelle deklarieren, kann sie von jeder Seite in Ihrer App verwendet werden.

BR211380.wedge(de-de,WIN.10).gifSo fügen Sie die App-Ressource "dateConverter " hinzu

  1. Doppelklicken Sie zum Öffnen im Projektmappen-Explorer auf App.xaml.
  2. Fügen Sie die Ressourcendeklaration <local:DateConverter x:Key="dateConverter" /> dem ResourceDictionarynach der feedDataSource-Ressource hinzu.

Nun können Sie den DateConverter in den Bindungen des Datumsblocks verwenden, der im nächsten Schritt erstellt wird. Bei diesem Konverter verwendet das Bindungsmodul Ihren benutzerdefinierten DateConverter, um einen DateTime-Typ in eine Zeichenfolge zu ändern. Die zurückgegebene Zeichenfolge wird wie gewünscht nur mit Tag, Monat und Jahr formatiert.

In App.xaml fügen Sie eine ControlTemplate hinzu, die ein Quadrat mit dem Datum anzeigt. Sie definieren dieses Element in App.xaml, damit Sie es sowohl in ItemsPage.xaml als auch in SplitPage.xaml verwenden können.

BR211380.wedge(de-de,WIN.10).gifSo fügen Sie App.xaml eine Steuerelementvorlage hinzu

  1. Doppelklicken Sie zum Öffnen im Projektmappen-Explorer auf App.xaml.
  2. Fügen Sie dieses XAML im ResourceDictionary mit den App-spezifischen Ressourcen nach der WindowsBlogLayoutRootStyle-Ressource hinzu.
    
    
    <ControlTemplate x:Key="DateBlockTemplate">
        <Canvas Height="86" Width="86"  Margin="8,8,0,8" HorizontalAlignment="Left" VerticalAlignment="Top">
            <TextBlock TextTrimming="WordEllipsis" TextWrapping="NoWrap" 
                       Width="Auto" Height="Auto" Margin="8,0,4,0" 
                       FontSize="32" FontWeight="Bold">
                <TextBlock.Text>
                    <Binding Path="PubDate" Converter="{StaticResource dateConverter}" ConverterParameter="month"  />
                </TextBlock.Text>
            </TextBlock>
    
            <TextBlock TextTrimming="WordEllipsis" TextWrapping="Wrap" 
                       Width="40" Height="Auto" Margin="8,0,0,0" 
                       FontSize="34" FontWeight="Bold" Canvas.Top="36">
                <TextBlock.Text>
                    <Binding Path="PubDate" Converter="{StaticResource dateConverter}" ConverterParameter="day"  />
                </TextBlock.Text>
            </TextBlock>
            <Line Stroke="White" StrokeThickness="2" X1="54" Y1="46" X2="54" Y2="80" />
    
            <TextBlock TextWrapping="Wrap" 
                Width="20" Height="Auto" 
                FontSize="{StaticResource ControlContentThemeFontSize}" Canvas.Top="42" Canvas.Left="60">
                <TextBlock.Text>
                    <Binding Path="PubDate" Converter="{StaticResource dateConverter}" ConverterParameter="year"  />
                </TextBlock.Text>
            </TextBlock>
        </Canvas>
    </ControlTemplate>
    
    

Nun können Sie mit dieser Steuerelementvorlage in SplitPage.xaml die Darstellung der Listenelemente in der Standardansicht aktualisieren.

BR211380.wedge(de-de,WIN.10).gifSo verwenden Sie die Steuerelementvorlage in SplitPage.xaml

  1. Doppelklicken Sie zum Öffnen im Projektmappen-Explorer auf SplitPage.xaml.
  2. Suchen Sie im XAML-Editor die zuvor erstellte DefaultListItemTemplate-Ressource.
  3. Ersetzen Sie das XAML für das Border-Element durch dieses XAML.
    
                    <Border Background="#FF6BBD46" Width="110" Height="110">
                        <ContentControl Template="{StaticResource DateBlockTemplate}" />
                    </Border>
    
    
  4. Ersetzen Sie das XAML für die drei TextBlock-Klassen im StackPanel-Element durch dieses XAML.
    
                        <TextBlock Text="{Binding Title}" FontSize="26.667" TextWrapping="Wrap"
                                   MaxHeight="72" Foreground="#FFFE5815" />
                        <TextBlock Text="{Binding Author}" FontSize="18.667" />
    
    

Hier sehen Sie das aktualisierte XAML für die Datenvorlage.



        <DataTemplate x:Key="DefaultListItemTemplate">
            <Grid Height="110" Margin="6">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <Border Background="#FF6BBD46" Width="110" Height="110">
                    <ContentControl Template="{StaticResource DateBlockTemplate}" />
                </Border>
                <StackPanel Grid.Column="1" VerticalAlignment="Top" Margin="10,0,0,0">
                    <TextBlock Text="{Binding Title}" FontSize="26.667" TextWrapping="Wrap"
                               MaxHeight="72" Foreground="#FFFE5815" />
                    <TextBlock Text="{Binding Author}" FontSize="18.667" />
                </StackPanel>
            </Grid>
        </DataTemplate>

Wichtig  Diese Vorlage wird im standardmäßigen Querformat im Vollbildmodus verwendet. Beträgt die Bildschirmauflösung weniger als 1366 Pixel in der Breite, wird für die geteilte Seite der FilledOrNarrow-Ansichtszustand verwendet. Diese Vorlage wird dann nicht in der Listenansicht angezeigt. Führen Sie zum Anzeigen dieser Vorlage die App im Simulator in Visual Studio mit einer Auflösung von mind. 1366 x 768 aus. Weitere Informationen zum Testen der App im Simulator finden Sie unter Ausführen von Windows Store-Apps über Visual Studio.

Um die Formatierung der geteilten Seite abzuschließen, müssen Sie die Hintergrundfarbe der App-Leiste und die Farbe des ausgewählten Elements in der Listenansicht ändern.

BR211380.wedge(de-de,WIN.10).gifSo aktualisieren Sie den Hintergrund der App-Leiste

  1. Wählen Sie in SplitPage.xaml das AppBar-Steuerelement aus.
  2. Legen Sie die Background-Eigenschaft im Eigenschaftenbereich unter Brush oder im XAML-Editor auf "#F20A2562" fest.
    
    <AppBar Padding="10,0,10,0" Background="#F20A2562">
    
    

Standardmäßig hat das ausgewählte Element in der Listenansicht einen violetten Hintergrund. Sie überschreiben die standardmäßigen Brush-Elemente für das Listenansichtdesign, um das ausgewählte Element blau darzustellen. Um integrierte Brush-Elemente für das Design außer Kraft zu setzen, definieren Sie ein Brush-Element mit demselben Schlüssel in App.xaml und geben ihm einen neuen Wert.

BR211380.wedge(de-de,WIN.10).gifSo aktualisieren Sie die Farben der Listenansicht

  1. Doppelklicken Sie zum Öffnen im Projektmappen-Explorer auf App.xaml.
  2. Fügen Sie dieses XAML im ResourceDictionary nach Ihren anderen App-spezifischen Ressourcen hinzu.
    
    
    <SolidColorBrush x:Key="ListViewItemSelectedBackgroundThemeBrush" Color="#FF465985"/>
    <SolidColorBrush x:Key="ListViewItemSelectedPointerOverBackgroundThemeBrush" Color="#FF384A72"/>
    <SolidColorBrush x:Key="ListViewItemSelectedPointerOverBorderThemeBrush" Color="#FF384A72" />
    
    

Wenden Sie zum Abschließen der App-Formatierung ähnliche Stile auf die Elementseite an. In ItemsPage.xaml fügen Sie die folgenden Ressourcen hinzu, um das Erscheinungsbild der Rasterelemente in der Standardansicht anzupassen:

BR211380.wedge(de-de,WIN.10).gifSo formatieren Sie ItemsPage.xaml

  1. Doppelklicken Sie zum Öffnen im Projektmappen-Explorer auf ItemsPage.xaml.
  2. Fügen Sie im XAML-Editor dieses XAML nach der AppName-Ressource dem Abschnitt Page.Resources hinzu.
    
    
            <!-- light blue -->
            <SolidColorBrush x:Key="BlockBackgroundBrush" Color="#FF557EB9"/>
    
            <!-- Grid Styles -->
            <Style x:Key="GridTitleTextStyle" TargetType="TextBlock" BasedOn="{StaticResource BasicTextStyle}">
                <Setter Property="FontSize" Value="26.667"/>
                <Setter Property="Margin" Value="12,0,12,2"/>
            </Style>
    
            <Style x:Key="GridDescriptionTextStyle" TargetType="TextBlock" BasedOn="{StaticResource BasicTextStyle}">
                <Setter Property="VerticalAlignment" Value="Bottom"/>
                <Setter Property="Margin" Value="12,0,12,60"/>
            </Style>
    
            <DataTemplate x:Key="DefaultGridItemTemplate">
                <Grid HorizontalAlignment="Left" Width="250" Height="250">
                    <Border Background="{StaticResource BlockBackgroundBrush}" />
                    <TextBlock Text="{Binding Title}" Style="{StaticResource GridTitleTextStyle}"/>
                    <TextBlock Text="{Binding Description}" Style="{StaticResource GridDescriptionTextStyle}" />
                    <StackPanel VerticalAlignment="Bottom" Orientation="Horizontal"
                            Background="{StaticResource ListViewItemOverlayBackgroundThemeBrush}">
                        <TextBlock Text="Last Updated" Margin="12,4,0,8" Height="42"/>
                        <TextBlock Text="{Binding PubDate, Converter={StaticResource dateConverter}}" Margin="12,4,12,8" />
                    </StackPanel>
                </Grid>
            </DataTemplate>
    
    
  3. Wählen Sie das GridView-Steuerelement itemGridView aus.
  4. Klicken Sie im Eigenschaftenpanel unter Sonstiges auf den Eigenschaftsmarker für die ItemTemplate-Eigenschaft. Das Eigenschaftenmenü wird geöffnet.
  5. Klicken Sie im Menü auf Lokale Ressource > DefaultGridItemTemplate.

    Hinweis  Die XAML-Seite Entwurfsansicht muss in Visual Studio angezeigt werden. Wird nur der XAML-Editor angezeigt, werden lokale Seitenressourcen nicht aufgeführt.

    Hier ist das vollständige aktualisierte XAML für itemGridView angegeben.

    
    
            <!-- Horizontal scrolling grid used in most view states -->
            <GridView
                x:Name="itemGridView"
                AutomationProperties.AutomationId="ItemsGridView"
                AutomationProperties.Name="Items"
                TabIndex="1"
                Grid.RowSpan="2"
                Padding="116,136,116,46"
                ItemsSource="{Binding Source={StaticResource itemsViewSource}}"
                
                ItemTemplate="{StaticResource DefaultGridItemTemplate}"
                
                SelectionMode="None"
                IsSwipeEnabled="false" 
                IsItemClickEnabled="True" 
                ItemClick="ItemView_ItemClick"/>
    
    
  6. Drücken Sie F5, um die App zu erstellen und auszuführen. Von der Elementseite wird nun die neue Vorlage verwendet.

Mit den neuen Stilen passt Ihre App wunderbar zum Erscheinungsbild der Website mit den Windows-Teamblogs:

Sammlungsseite mit Stil

Geteilte Seite mit Stil

Detailseite mit Stil

Mit Stilen und Stilvorlagen können Sie schnell ein unterschiedliches Aussehen für Ihre App definieren und anwenden. Im nächsten Abschnitt verbinden Sie das über Animationen und Stile Gelernte und sorgen dafür, dass sich Ihre App während der Ausführung nahtlos verschiedenen Layouts und Ausrichtungen anpasst.

Anpassung an verschiedene Layouts

Hinweis  In diesem Abschnitt wenden Sie die in Teil 3: Navigation, Layout und Ansichten besprochenen Konzepte an. Weitere Informationen zum Anpassen Ihrer UI an verschiedene Ansichten sowie entsprechende Tools finden Sie in Teil 3.

In der Regel wird eine App für eine Ansicht im Vollbildmodus und im Querformat entwickelt. Eine Windows Store-App muss sich aber unterschiedlichen Ausrichtungen und Layouts anpassen können. Insbesondere muss sie sowohl das Querformat als auch das Hochformat unterstützen. Im Querformat müssen die Layouts Vollbild, Gefüllt und Angedockt unterstützt werden.

Tipp  Wenn Sie die App in unterschiedlichen Ausrichtungen und Auflösungen testen möchten, können Sie sie im Simulator ausführen. Wählen Sie auf der Standardsymbolleiste in der Dropdownliste neben der Schaltfläche Debuggen starten die Option Simulator aus, um Ihre Windows Store-App im Simulator zu starten. Weitere Informationen zum Simulator finden Sie unter Ausführen von Windows Store-Apps über Visual Studio.

Die Visual Studio-Vorlagen enthalten Code, mit dem Änderungen des Ansichtszustands behandelt werden. Dieser Code befindet sich in der Datei LayoutAwarePage.cs/vb und ordnet den Zustand Ihrer App den in Ihrem XAML definierten Ansichtszuständen zu. Da Ihnen die Logik für das Seitenlayout zur Verfügung gestellt wird, müssen Sie nur noch die gewünschten Ansichten für die einzelnen Ansichtszustände der Seite angeben.

Für den Übergang zwischen verschiedenen Ansichten mithilfe von XAML verwenden Sie den VisualStateManager, um unterschiedliche VisualState-Elemente für die App zu definieren. Hier haben Sie eine VisualStateGroup in ItemsPage.xaml definiert. Diese Gruppe umfasst vier VisualStates: FullScreenLandscape, Filled, FullScreenPortrait und Snapped. Es ist nicht möglich, gleichzeitig verschiedene VisualStates aus derselben VisualStateGroup zu verwenden. Jeder VisualState besitzt Animationen, mit denen der App mitgeteilt wird, welche Änderungen an den Grundwerten vorgenommen werden sollen, die im XAML für die UI angegeben sind.


<!--App Orientation States-->
  <VisualStateManager.VisualStateGroups>
     <VisualStateGroup x:Name="ApplicationViewStates">
        <VisualState x:Name="FullScreenLandscape" />
        <VisualState x:Name="Filled"> ... </VisualState>
        <VisualState x:Name="FullScreenPortrait"> ... </VisualState>
        <VisualState x:Name="Snapped"> ... </VisualState>
    </VisualStateGroup>
 </VisualStateManager.VisualStateGroups>

Sie verwenden den Zustand FullScreenLandscape, wenn sich die App im Querformat und im Vollbildmodus befindet. Da Sie die Standardbenutzeroberfläche für diese Ansicht erstellt haben, sind keine Änderungen nötig, und der VisualState ist leer.

Sie verwenden den Zustand Filled, wenn der Benutzer eine andere App an einer Bildschirmseite angedockt hat. Die Seite mit der Elementansicht wird in diesem Fall einfach verschoben, und es sind keine Änderungen nötig. Das ist ebenfalls ein leerer VisualState.

Sie verwenden den Zustand FullScreenPortrait, wenn Ihre App vom Quer- ins Hochformat gedreht wird. Dieser Ansichtszustand enthält zwei Animationen. Eine ändert den Stil für die Zurück-Schaltfläche, die andere ändert den Rand von itemGridView, sodass alles besser auf den Bildschirm passt.


<!-- The entire page respects the narrower 100-pixel margin convention for portrait -->
<VisualState x:Name="FullScreenPortrait">
    <Storyboard>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="backButton" 
                                       Storyboard.TargetProperty="Style">
            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PortraitBackButtonStyle}"/>
        </ObjectAnimationUsingKeyFrames>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemGridView" 
                                       Storyboard.TargetProperty="Padding">
            <DiscreteObjectKeyFrame KeyTime="0" Value="96,136,86,56"/>
        </ObjectAnimationUsingKeyFrames>
    </Storyboard>
</VisualState>


Den Zustand Snapped verwenden Sie, wenn zwei Apps angezeigt werden und Ihre App die schmalere von beiden ist. In diesem Zustand ist Ihre App nur 320 geräteunabhängige Pixel (Device-Independent Pixel, DIP) breit. Es sind also entscheidendere Änderungen am Layout nötig. Im XAML für die UI der Elementseite sind eine GridView und eine ListView definiert und an die Datenauflistung gebunden. itemGridView ist standardmäßig eingeblendet, und itemListView ausgeblendet. Im Zustand Snapped haben Sie vier Animationen. Diese dienen zum Reduzieren der itemGridView, zum Anzeigen der itemListView sowie zum Ändern des Styles der Zurück-Schaltfläche und des Seitentitels, um sie zu verkleinern.


<!--
    The back button and title have different styles when snapped, and the list representation is substituted
    for the grid displayed in all other view states
-->
<VisualState x:Name="Snapped">
    <Storyboard>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="backButton" 
                                       Storyboard.TargetProperty="Style">
            <DiscreteObjectKeyFrame KeyTime="0" 
                                    Value="{StaticResource SnappedBackButtonStyle}"/>
        </ObjectAnimationUsingKeyFrames>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="pageTitle" 
                                       Storyboard.TargetProperty="Style">
            <DiscreteObjectKeyFrame KeyTime="0" 
                                    Value="{StaticResource SnappedPageHeaderTextStyle}"/>
        </ObjectAnimationUsingKeyFrames>

        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemListView" 
                                       Storyboard.TargetProperty="Visibility">
            <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
        </ObjectAnimationUsingKeyFrames>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemGridView"
                                       Storyboard.TargetProperty="Visibility">
            <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
        </ObjectAnimationUsingKeyFrames>
    </Storyboard>
</VisualState>

Im Abschnitt Erzielen eines einheitlichen Aussehens mit Stilen dieses Lernprogramms haben Sie Stile und Vorlagen erstellt, um das Erscheinungsbild der App anzupassen. Diese Stile und Vorlagen werden in der standardmäßigen Querformatansicht verwendet. Damit das angepasste Erscheinungsbild in unterschiedlichen Ansichten erhalten bleibt, müssen Sie für diese Ansichten ebenfalls benutzerdefinierte Vorlagen erstellen.

In ItemsPage.xaml haben Sie eine neue Datenvorlage für die Rasterelemente erstellt. Sie müssen auch eine neue Datenvorlage für die Listenelemente in der Snapped-Ansicht bereitstellen. Sie nennen diese Vorlage NarrowListItemTemplate und fügen sie dem Ressourcenabschnitt von ItemsPage.xaml direkt im Anschluss an die DefaultGridItemTemplate-Ressource hinzu.

BR211380.wedge(de-de,WIN.10).gifSo fügen Sie eine Vorlage für die angedockte Ansicht hinzu

  1. Doppelklicken Sie zum Öffnen im Projektmappen-Explorer auf ItemsPage.xaml.
  2. Fügen Sie im XAML-Editor dieses XAML nach der DefaultGridItemTemplate-Ressource dem Abschnitt Page.Resources hinzu.
    
            <!-- Used in Snapped view -->
            <DataTemplate x:Key="NarrowListItemTemplate">
                <Grid Height="80">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto"/>
                        <ColumnDefinition Width="*"/>
                    </Grid.ColumnDefinitions>
                    <Border Background="{StaticResource BlockBackgroundBrush}" Width="80" Height="80" />
                    <ContentControl Template="{StaticResource DateBlockTemplate}" Margin="-12,-12,0,0"/>
                    <StackPanel Grid.Column="1" HorizontalAlignment="Left" Margin="12,8,0,0">
                        <TextBlock Text="{Binding Title}" MaxHeight="56" TextWrapping="Wrap"/>
                    </StackPanel>
                </Grid>
            </DataTemplate>
    
    
  3. Wählen Sie das ListView-Steuerelement itemListView aus.
  4. Klicken Sie im Eigenschaftenpanel unter Sonstiges auf den Eigenschaftsmarker für die ItemTemplate-Eigenschaft. Das Eigenschaftenmenü wird geöffnet.
  5. Wählen Sie im Menü Lokale Ressource > NarrowListItemTemplate aus.

    Hier sehen Sie das vollständige aktualisierte XAML für itemListView.

    
    
            <!-- Vertical scrolling list only used when snapped -->
            <ListView
                x:Name="itemListView"
                AutomationProperties.AutomationId="ItemsListView"
                AutomationProperties.Name="Items"
                TabIndex="1"
                Grid.Row="1"
                Visibility="Collapsed"
                Margin="0,-10,0,0"
                Padding="10,0,0,60"
                ItemsSource="{Binding Source={StaticResource itemsViewSource}}"
                ItemTemplate="{StaticResource NarrowListItemTemplate}"
                SelectionMode="None"
                IsSwipeEnabled="false" 
                IsItemClickEnabled="True" 
                ItemClick="ItemView_ItemClick"/>
    
    

Die Elementseite weist sowohl eine GridView als auch eine ListView auf. Die Vorlagen werden für das Standard-XAML verwendet. Sie zeigen die GridView für die Standardansicht an. Beim Wechsel zur angedockten Ansicht ersetzen Sie das Raster mit dem VisualStateManager durch die ListView, um die Visibility-Eigenschaften der beiden Ansichten zu ändern.

Die UI der geteilten Seite wird bei einer Änderung der Ansicht auf andere Weise geändert. Sie haben eine ListView, die in allen Ansichten angezeigt wird. Um die Darstellung dieser Ansicht zu ändern, wenn sich die Ansicht ändert, wird mit dem VisualStateManager eine neue Vorlage auf die ListView angewendet.

In SplitPage.xaml erstellen Sie eine ähnliche ListView-Vorlage, die in den Ansichten Filled und Snapped verwendet wird. Die Vorlage wird außerdem in der FullScreenLandscape-Ansicht verwendet, sofern die Bildschirmbreite weniger als 1366 DIP beträgt. Sie nennen diese Vorlage ebenfalls NarrowListItemTemplate und fügen sie dem Ressourcenabschnitt von SplitPage.xaml direkt im Anschluss an die DefaultListItemTemplate-Ressource hinzu.

BR211380.wedge(de-de,WIN.10).gifSo fügen Sie eine schmale Vorlage hinzu

  1. Doppelklicken Sie zum Öffnen im Projektmappen-Explorer auf SplitPage.xaml.
  2. Fügen Sie im XAML-Editor dieses XAML nach der DefaultListItemTemplate-Ressource dem Abschnitt Page.Resources hinzu.
    
    
            <!-- green -->
            <SolidColorBrush x:Key="BlockBackgroundBrush" Color="#FF6BBD46"/>
    
            <!-- Used in Filled and Snapped views -->
            <DataTemplate x:Key="NarrowListItemTemplate">
                <Grid Height="80">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto"/>
                        <ColumnDefinition Width="*"/>
                    </Grid.ColumnDefinitions>
                    <Border Background="{StaticResource BlockBackgroundBrush}" 
                            Width="80" Height="80"/>
                    <ContentControl Template="{StaticResource DateBlockTemplate}" 
                                    Margin="-12,-12,0,0"/>
                    <StackPanel Grid.Column="1" HorizontalAlignment="Left" 
                                Margin="12,8,0,0">
                        <TextBlock Text="{Binding Title}" MaxHeight="56" 
                                   Foreground="#FFFE5815" TextWrapping="Wrap"/>
                        <TextBlock Text="{Binding Author}" FontSize="12" />
                    </StackPanel>
                </Grid>
            </DataTemplate>
    
    

Um diese Datenvorlage zu verwenden, müssen Sie die Ansichtszustände aktualisieren, in denen sie zum Einsatz kommt.

BR211380.wedge(de-de,WIN.10).gifSo aktualisieren Sie die Ansichtszustände

  1. Im XAML für die Ansichtszustände FilledOrNarrow und Snapped suchen wir nach den Animationen für die ItemTemplate-Eigenschaft von itemListView.

    Tipp  Falls Sie das Element nicht sofort finden, drücken Sie STRG+F, um das Feld "Schnellsuche" zu öffnen, und suchen Sie nach "Standard80ItemTemplate".

  2. Ändern Sie den Wert, der in der NarrowListItemTemplate-Ressource verwendet werden soll, wie folgt: Value="{StaticResource NarrowListItemTemplate}".

    Sie verwenden Ihre benutzerdefinierte Vorlage anstelle der Standardressource Standard80ItemTemplate.

Hier sehen Sie das aktualisierte XAML für die Animationen.



<VisualState x:Name="FilledOrNarrow">
    <Storyboard>
    ....
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemListView" Storyboard.TargetProperty="ItemTemplate">
            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource NarrowListItemTemplate}"/>
        </ObjectAnimationUsingKeyFrames>
    ....
    </Storyboard>
</VisualState>
...
<VisualState x:Name="Snapped">
    <Storyboard>
    ....
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemListView" Storyboard.TargetProperty="ItemTemplate">
            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource NarrowListItemTemplate}"/>
        </ObjectAnimationUsingKeyFrames>
    ....
    </Storyboard>
</VisualState>

Sie haben auch den Abschnitt für die Artikeldetails der geteilten Seite durch Ihren eigenen Detailabschnitt ersetzt, in dem eine WebView verwendet wird. Aufgrund dieser Änderung beziehen sich die Animationen in den Zielelementen des Ansichtszustands Snapped_Detail auf nicht mehr vorhandene Elemente. Da diese beim Andocken der App zu Fehlern führen, müssen Sie sie entfernen.

BR211380.wedge(de-de,WIN.10).gifSo entfernen Sie nicht verwendete Animationen

  • In SplitPage.xaml entfernen wir diese Animationen aus dem Ansichtszustand Snapped_Detail.
    
    
    <VisualState x:Name="Snapped_Detail">
        <Storyboard>
        ...
            <!--<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemDetailTitlePanel" Storyboard.TargetProperty="(Grid.Row)">
                    <DiscreteObjectKeyFrame KeyTime="0" Value="0"/>
                </ObjectAnimationUsingKeyFrames>
                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemDetailTitlePanel" Storyboard.TargetProperty="(Grid.Column)">
                    <DiscreteObjectKeyFrame KeyTime="0" Value="0"/>
                </ObjectAnimationUsingKeyFrames>-->
       ...
            <!--<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemSubtitle" Storyboard.TargetProperty="Style">
                    <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource CaptionTextStyle}"/>
                </ObjectAnimationUsingKeyFrames>-->
        </Storyboard>
    </VisualState>
    
    

Wenn Sie einen Blog auswählen und zur geteilten Seite in der angedockten Ansicht navigieren, sollte die Liste der Blogbeiträge angezeigt werden. Stattdessen wird jedoch der Text des ersten Blogbeitrags angezeigt, da diese Auswahl standardmäßig festgelegt ist. Um das Standardverhalten zu ändern, vergewissern Sie sich, dass beim Navigieren zur geteilten Seite in der angedockten Ansicht keine Auswahl getroffen wurde.

BR211380.wedge(de-de,WIN.10).gifSo heben Sie die Auswahl des ersten Elements auf

  1. Doppelklicken Sie zum Öffnen im Projektmappen-Explorer auf SplitPage.xaml.cs/vb.
  2. Suchen Sie in der LoadState-Methode zunächst nach diesem Codeblock.
    
                if (pageState == null)
                {
                    // When this is a new page, select the first item automatically unless logical page
                    // navigation is being used (see the logical page navigation #region below.)
                    if (!this.UsingLogicalPageNavigation() && this.itemsViewSource.View != null)
                    {
                        this.itemsViewSource.View.MoveCurrentToFirst();
                    }
                }
    
    
  3. Fügen Sie die else-Klausel wie hier gezeigt hinzu. Durch den Aufruf von MoveCurrentToPosition(-1) wird bewirkt, dass das erste Element nicht festgelegt ist.
    
                if (pageState == null)
                {
                    // When this is a new page, select the first item automatically unless logical page
                    // navigation is being used (see the logical page navigation #region below.)
                    if (!this.UsingLogicalPageNavigation() && this.itemsViewSource.View != null)
                    {
                        this.itemsViewSource.View.MoveCurrentToFirst();
                    }
                    else
                    {
                        this.itemsViewSource.View.MoveCurrentToPosition(-1);
                    }
                }
    
    

In DetailPage.xaml müssen Sie nur den Rand der WebView in der Snapped-Ansicht so anpassen, dass der gesamte verfügbare Platz genutzt wird.

BR211380.wedge(de-de,WIN.10).gifSo aktualisieren Sie DetailPage.xaml

  1. Doppelklicken Sie zum Öffnen im Projektmappen-Explorer auf DetailPage.xaml.
  2. Dem XAML für den Ansichtszustand Snapped fügen wir eine Animation hinzu, um den Wert der Margin-Eigenschaft für contentViewBorder zu ändern.
    
    
            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="contentViewBorder" Storyboard.TargetProperty="Margin">
                <DiscreteObjectKeyFrame KeyTime="0" Value="20,5,20,20"/>
            </ObjectAnimationUsingKeyFrames>
    >
    
    

Hier sehen Sie das vollständige XAML für den angedockten Zustand.



                <!-- The back button and title have different styles when snapped -->
                <VisualState x:Name="Snapped">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="backButton" Storyboard.TargetProperty="Style">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource SnappedBackButtonStyle}"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="pageTitle" Storyboard.TargetProperty="Style">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource SnappedPageHeaderTextStyle}"/>
                        </ObjectAnimationUsingKeyFrames>

                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="contentViewBorder" Storyboard.TargetProperty="Margin">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="20,5,20,20"/>
                        </ObjectAnimationUsingKeyFrames>

                    </Storyboard>
                </VisualState>

Drücken Sie F5, um die App zu erstellen und auszuführen. Probieren Sie unterschiedliche Ansichten und Ausrichtungen aus.

Verwalten des App-Lebenszyklus und -Status

Hinweis  In diesem Abschnitt wenden Sie die in Teil 2: Verwalten von App-Lebenszyklus und -Zustand besprochenen Konzepte an. Weitere Infos zum Speichern von App-Zuständen finden Sie in Teil 2.

Um Systemressourcen einzusparen, werden ausgeführte Windows Store-Apps vom System automatisch angehalten (und manchmal sogar beendet), die im Hintergrund ausgeführt werden. Eine gute App kann vom System angehalten, beendet und neu gestartet werden und wirkt trotzdem immer so, als wäre sie ununterbrochen ausgeführt worden. An dieser Stelle fügen Sie Code zum Behandeln der Unterbrechung und Fortsetzung der App hinzu. Die erforderliche Infrastruktur wird glücklicherweise überwiegend durch die LayoutAwarePage- und die SuspensionManager-Klasse in Visual Studio-Vorlagen bereitgestellt. Sie müssen daher nur noch ein bisschen Code zum Speichern und Wiederherstellen von Einstellungen hinzufügen.

Verwalten des Navigationszustands

Um den App-Zustand mit der SuspensionManager-Klasse zu verwalten, registrieren Sie das Frame-Stammelement mit Ihrem Inhalt unter Verwendung des SuspensionManager. Sobald die App unterbrochen wird, rufen Sie SuspensionManager.SaveAsync auf, um den Navigationszustand der App zu speichern. Dazu gehören auch Informationen darüber, welche Seite die aktuelle Seite ist und welcher Navigationsparameter an die Seite übergeben wurde. Wenn die App wiederhergestellt wird, wird der Navigationszustand wiederhergestellt, und der Navigationsparameter wird wieder an die Seite übergeben.

BR211380.wedge(de-de,WIN.10).gifSo speichern Sie den Navigationszustand

  1. Doppelklicken Sie zum Öffnen im Projektmappen-Explorer auf App.xaml.cs/vb.
  2. Fügen Sie das async-Schlüsselwort der OnSuspending-Methode hinzu.
    
    private async void OnSuspending(object sender, SuspendingEventArgs e)
    
    
  3. Fügen Sie diesen Code der OnSuspending-Methode nach dem "TODO"-Kommentar hinzu.

    SuspensionManager.SaveAsync speichert den Navigationszustand des Frame und ermöglicht es der Page dann, den zugehörigen Inhalt zu speichern.

    
                //TODO: Save application state and stop any background activity
                await WindowsBlogReader.Common.SuspensionManager.SaveAsync();
    
    

Wenn die App nach einer Unterbrechung und Beendigung wiederhergestellt wird, wird dieser Code ausgeführt, um den Navigationszustand der App wiederherzustellen.

BR211380.wedge(de-de,WIN.10).gifSo laden Sie den Navigationszustand

  1. Fügen Sie diesen Code in App.xaml.cs/vb in der OnLaunched-Methode unmittelbar nach der Instanziierung des neuen Frame hinzu.

    An dieser Stelle registrieren Sie den Frame mit der SuspensionManager-Klasse.

    
                    // Add this code after "rootFrame = new Frame();"
                    WindowsBlogReader.Common.SuspensionManager.RegisterFrame(rootFrame, "AppFrame");
    
    
  2. Fügen Sie diesen Code in der OnLaunched-Methode nach dem "TODO"-Kommentar hinzu.

    SuspensionManager.RestoreAsync stellt den Navigationszustand des Frame wieder her und ermöglicht der Page anschließend das Wiederherstellen des Inhalts.

    
                        //TODO: Load state from previously suspended application
                        await WindowsBlogReader.Common.SuspensionManager.RestoreAsync();
    
    

Verwalten des Seitenzustands

Wenn die App unterbrochen und wiederhergestellt wird, müssen wir auch die seitenspezifischen Einstellungen speichern. In der Blogleser-App muss dabei nur das ausgewählte Element auf der geteilten Seite gespeichert und wiederhergestellt werden. Dazu verwenden Sie die SaveState- und die LoadState-Methode. Diese Methoden werden von der LayoutAwarePage-Klasse bereitgestellt.

BR211380.wedge(de-de,WIN.10).gifSo speichern Sie den Seitenzustand

  1. Doppelklicken Sie zum Öffnen im Projektmappen-Explorer auf SplitPage.xaml.cs/vb.
  2. Fügen Sie diesen Code in der SaveState-Methode nach der "TODO"-Anweisung hinzu.

    Die SuspensionManager-Klasse serialisiert und speichert das pageState-Wörterbuch in einer XML-Datei. Daten, die in pageState gespeichert werden, werden nur für die aktuelle Sitzung gespeichert. An dieser Stelle speichern Sie den Titel des ausgewählten Blogbeitrags in der Liste.

    
                    // TODO: Derive a serializable navigation parameter and assign it to
                    //       pageState["SelectedItem"]
                    if (selectedItem != null)
                    {
                        string itemTitle = ((FeedItem)selectedItem).Title;
                        pageState["SelectedItem"] = itemTitle;
                    }
    
    
    

BR211380.wedge(de-de,WIN.10).gifSo laden Sie den Seitenzustand

  • Fügen Sie diesen Code in SplitPage.xaml.cs/vb in der LoadState-Methode nach dem dritten "TODO"-Kommentar hinzu.
    
                        // TODO: Invoke this.itemsViewSource.View.MoveCurrentTo() with the selected
                        //       item as specified by the value of pageState["SelectedItem"]
    
                        string itemTitle = (string)pageState["SelectedItem"];
                        FeedItem selectedItem = FeedDataSource.GetItem(itemTitle);
                        this.itemsViewSource.View.MoveCurrentTo(selectedItem);
    
    

Hinzufügen eines Begrüßungsbildschirms und Logos

Mit dem Logo und dem Begrüßungsbildschirm gewinnt der Benutzer den ersten Eindruck von Ihrer App. Das Logo erscheint im Windows Store und auf dem Startbildschirm. Der Begrüßungsbildschirm wird direkt angezeigt, wenn ein Benutzer die App startet. Er stellt die erste Interaktion mit dem Benutzer dar, während die App ihre Ressourcen initialisiert. Sobald die erste Seite der App angezeigt werden kann, wird der Begrüßungsbildschirm geschlossen.

Er besteht aus einer Hintergrundfarbe und einem Bild mit 620 x 300 Pixeln. Diese Werte legen Sie in der Datei Package.appxmanifest fest. Doppelklicken Sie auf diese Datei, um sie im Manifest-Editor zu öffnen. Auf der Registerkarte Anwendungsbenutzeroberfläche des Manifest-Editors legen Sie den Pfad zum Bild unseres Begrüßungsbildschirms und die Hintergrundfarbe fest. Die Projektvorlage enthält standardmäßig ein leeres Bild mit dem Namen SplashScreen.png. Sie ersetzen dies mit Ihrem eigenen Bild für den Begrüßungsbildschirm, das Ihre App identifiziert und umgehend die Aufmerksamkeit des Benutzers auf die App zieht. Sie können auch ein Logo angeben, indem Sie die Vorlagendateien für Logos durch Ihre eigenen ersetzen. Und so sieht der Begrüßungsbildschirm für den Blogleser aus:

Bild des Begrüßungsbildschirms

Der einfache Begrüßungsbildschirm reicht für den Blogleser völlig aus. Sie können das Bild aber mit Eigenschaften und Methoden der SplashScreen-Klasse erweitern. Mit der SplashScreen-Klasse können Sie die Koordinaten des Begrüßungsbildschirms abrufen und damit die erste Seite der App platzieren. Sie können auch feststellen, wann der Begrüßungsbildschirm geschlossen wird. Dann wissen Sie, wann Animationen für den Eingang von Inhalten in der App gestartet werden sollten.

Siehe Code

Kommen Sie nicht voran, oder möchten Sie Ihre Arbeit überprüfen? Informationen hierzu finden Sie unter Blogleser: Vollständiger Code.

Nächste Schritte

Sie haben gelernt, wie Sie mit integrierten Seitenvorlagen aus Visual Studio Express 2012 für Windows 8 eine vollständige, aus mehreren Seiten bestehende App erstellen und wie die Navigation und das Übergeben von Daten zwischen den Seiten funktioniert. Ferner haben Sie gelernt, wie die App mit Stilen und Vorlagen den Merkmalen der Website mit den Windows-Teamblogs angeglichen werden kann. Darüber hinaus sind Sie jetzt mit der Verwendung von Designanimationen, einer App-Leiste und eines Begrüßungsbildschirm vertraut und können die App dem Charakter von Windows 8 anpassen. Außerdem wissen Sie nun, wie Sie die App an verschiedene Layouts und Ausrichtungen anpassen können, um stets eine optimale Darstellung zu gewährleisten.

Weitere Informationen zum Entwickeln von Apps finden Sie in der Liste mit den Lern- und Referenzressourcen für die Erstellung von Windows Store-Apps.

Roadmap für Windows Store-Apps mit C# oder Visual Basic

 

 

Anzeigen:
© 2014 Microsoft. Alle Rechte vorbehalten.