So wird's gemacht: Anpassen von Visual Studio-Vorlagendaten (HTML)

[ Dieser Artikel richtet sich an Windows 8.x- und Windows Phone 8.x-Entwickler, die Windows-Runtime-Apps schreiben. Wenn Sie für Windows 10 entwickeln, finden Sie weitere Informationen unter neueste Dokumentation]

In den Vorlagen"Hub/Pivot", "Hub", "Pivot", "Grid" und "Split" befindet sich der Code, der die für die App erforderlichen Daten enthält, in der Datei data.js. Diese Datei ist eine Beispieldatenquelle für die App. Die Datei data.js enthält statische Daten, die in der Regel durch dynamische Daten ersetzt werden müssen. Wenn Ihre App zum Beispiel RSS- oder JSON-Daten über eine einzelne xhr-Anforderung abruft, können Sie diesen Code in data.js einfügen. Wenn Sie den Code an dieser Stelle einfügen, können Sie problemlos eigene Daten verwenden, ohne das Datenmodell ändern zu müssen, das in den Vorlagen vorhanden ist.

Tipp  Die Vorlagen "Hub/Pivot", "Hub" und "Pivot" rufen auch statische Daten aus RESJSON-Dateien ab, die Globalisierung unterstützen. Weitere Informationen finden Sie unter Beispiel für das Binden von Daten an die UI in den Vorlagen „Hub/Pivot“, „Hub“ und „Pivot“.

 

Wenn Sie einer App eigene Daten hinzufügen, müssen Sie sich über einige Dinge im Klaren sein:

  • Gruppen und Elemente sind systemintern verknüpft. Die App erwartet, dass Elementdaten in Gruppen angeordnet sind. Sie können die Verknüpfung von Gruppen und Elementen in Ihrer eigenen Implementierung aufheben. Damit diese Implementierung funktioniert, müssen Sie jedoch Code ändern. In diesem Thema wird erklärt, wie Gruppen im Vorlagen-Datenmodell verwendet werden.
  • Wenn Sie benutzerdefinierte Daten für eine App in data.js implementieren, müssen Sie sicherstellen, dass die Eigenschaftennamen, die zu Ihren benutzerdefinierten Daten gehören, den Eigenschaftennamen zugeordnet sind, die von der Vorlage verwendet werden. Sie können die von der Vorlage verwendeten Namen ändern, aber dies erfordert weitere Codeänderungen. In diesem Thema wird anhand einiger Beispiels gezeigt, wie Sie vorgehen müssen.

Elemente und Gruppen

Die Vorlagendaten werden in einer WinJS.Binding.List gespeichert. Der folgende Code zeigt die Deklaration einer Liste in der Datei data.js.

var list = new WinJS.Binding.List();

Die sampleItems-Funktion übergibt ein Array der Elementdaten (im Beispiel WinJS.Binding.List) an die push:

generateSampleData.forEach(function (item) {
    list.push(item);
});

WinJS.Binding.List enthält die interne Logik zum Behandeln der Datengruppierung. Das sampleItems-Array enthält eine group-Eigenschaft, die die Gruppe angibt, zu der das Element gehört (in den Beispieldaten werden Gruppen im sampleGroups-Array angegeben). Dies ist das Array der Elementdaten in der generateSampleData-Funktion:

function generateSampleData() {
    // . . .
    var sampleGroups = [
        { key: "group1", title: "Group Title: 1", // . . .
        // . . .
    ];

    var sampleItems = [
        { group: sampleGroups[0], title: "Item Title: 1", // . . .
        // . . .
    ];

    return sampleItems;
}

Wenn Sie die App für Ihre benutzerdefinierten Daten ändern, können Sie zum Gruppieren der Daten demselben Muster folgen. Bei kleineren Datensätzen empfiehlt sich die Verwendung von WinJS.Binding.List für ListView. Wenn Sie Ihre Elemente nicht gruppieren, können Sie dennoch eine WinJS.Binding.List verwenden. Sie müssen dann jedoch den Vorlagencode überall dort ändern, wo die Vorlage gruppenbasierte Daten erwartet.

Tipp  WinJS.Binding.List ist eine synchrone Datenquelle, die ein JavaScript-Array verwendet. Bei sehr großen Datensätzen, die mehrere tausend Elemente umfassen können, müssen Sie möglicherweise eine asynchrone Datenquelle verwenden. Weitere Informationen finden Sie unter Verwenden des ListView-Steuerelements.

 

Die createGrouped-Funktion der WinJS.Binding.List gibt an, wie die Elemente mithilfe eines Gruppenschlüssels und Elementgruppenwerts gruppiert werden. Diese Funktion wird in data.js aufgerufen. key und group sind Eigenschaftennamen, die in den Beispieldatenarrays angegeben sind.

var groupedItems = list.createGrouped(
    function groupKeySelector(item) { return item.group.key; },
    function groupDataSelector(item) { return item.group; }
);

Wenn die Vorlagen-App eine Liste von Elementen benötigt, ruft sie getItemsFromGroup auf. Diese gibt eine WinJS.Binding.List zurück, die nur die zur angegebenen Gruppen gehörenden Elemente enthält.

function getItemsFromGroup(group) {
    return list.createFiltered(function (item) {
        return item.group.key === group.key;
    });
}

Tipp  Funkionen wie getItemsFromGroup, die createFiltered aufrufen, erstellen eine neue Projektion von WinJS.Binding.List, und möglicherweise muss das zurückgegebene Objekt verworfen werden, wenn von der Seite navigiert wird. Rufen Sie zum Verwerfen des Objekts die WinJS.Binding.List.dispose-Methode auf.

 

Die define-Funktion der Windows-Bibliothek für JavaScript macht die Daten für die App verfügbar, indem der Namespace Data mit einer Reihe öffentlicher Memberfunktionen angegeben wird.

WinJS.Namespace.define("Data", {
    items: groupedItems,
    groups: groupedItems.groups,
    getItemReference: getItemReference,
    getItemsFromGroup: getItemsFromGroup,
    resolveGroupReference: resolveGroupReference,
    resolveItemReference: resolveItemReference
});

Wenn Sie für die einzelnen Seiten in der App unterschiedliche Datenquellen oder Datenmodelle definieren möchten, müssen Sie alle Aufrufe dieser Member im JavaScript-Code ersetzen.

Binden von Gruppen- und Elementdaten an die UI

Der folgende Code enthält ein Beispiel für Markup des ListView-Steuerelements. Die Datenquelle für das ListView-Steuerelement wird wie hier gezeigt in der itemDataSource-Eigenschaft angegeben. Dieses Beispiel stammt aus der Datei split.html in der Vorlage "Split".


<div class="itemlist win-selectionstylefilled" aria-label="List of this group's items" data-win-control="WinJS.UI.ListView" data-win-options="{
    layout: {type: WinJS.UI.ListLayout},
    currentItem: {type: WinJS.UI.ObjectType.item, index: 0, hasFocus: true},
    selectionMode: 'single',
    swipeBehavior: 'none',
    tapBehavior: 'toggleSelect',
    itemDataSource: select('.pagecontrol').winControl.itemDataSource,
    itemTemplate: select('.itemtemplate'),
    onselectionchanged: select('.pagecontrol').winControl.selectionChanged
    }">
</div>

Im vorigen Code wird eine der Seite zugeordnete itemDataSource-Eigenschaft der itemDataSource-Eigenschaft des ListView-Steuerelements zugewiesen.

In den Vorlagen werden die Daten normalerweise entweder in der init-Funktion oder in der ready-Funktion an die UI gebunden. Diese Funktion ist in der JS-Datei definiert, die jeder HTML-Seite zugeordnet ist. Der folgende Code ist in der init-Funktion für split.html enthalten: In diesem Code ruft die App einen Gruppenverweis ab und dann das getItemsFromGroup-Element auf, das in data.js implementiert ist. Wie bereits erwähnt, gibt getItemsFromGroup eine WinJS.Binding.List zurück, die nur die Elemente in der angegebenen Gruppe enthält.

this._group = Data.resolveGroupReference(options.groupKey);
this._items = Data.getItemsFromGroup(this._group);

Anschließend binden wir die von getItemsFromGroup zurückgegebene Liste an die itemDataSource-Eigenschaft der Seite, mit der die Daten an das ListView-Steuerelement gebunden werden. Außerdem wird der Handler für die Elementauswahl (_selectionChanged) angegeben.


this.itemDataSource = this._items.dataSource;
this.selectionChanged = ui.eventHandler(this._selectionChanged.bind(this));

Zum Anzeigen der einzelnen Elemente im ListView-Steuerelement ordnet die App dem ListView-Steuerelement wie hier gezeigt eine Vorlage zu. Dieser Code wird im Markup für das ListView-Steuerelement angezeigt und nutzt die itemTemplate-Eigenschaft zum Angeben eines DIV-Elements mit dem Klassennamen itemtemplate.

itemTemplate: select('.itemtemplate')

WinJS-Vorlagen, die auf WinJS.Binding.Template basieren, werden zum Formatieren und Anzeigen mehrerer Dateninstanzen verwendet. In den Vorlagen "Grid App" und "Split App" wird als Vorlage am häufigsten die Elementvorlage verwendet, um die Elemente in einem ListView-Steuerelement anzuzeigen. Wie jedes WinJS-Vorlagenobjekt deklarieren Sie es, indem Sie ein data-win-control-Attribut hinzufügen und das Attribut auf WinJS.Binding.Template festlegen. Hier ist der HTML-Code für die itemtemplate in split.html:

<div class="itemtemplate" data-win-control="WinJS.Binding.Template">
    <div class="item">
        <img class="item-image" src="#" data-win-bind="src: backgroundImage; alt: title" />
        <div class="item-info">
            <h3 class="item-title win-type-ellipsis" 
                data-win-bind="textContent: title"></h3>
            <h6 class="item-subtitle win-type-ellipsis"
                data-win-bind="textContent: author"></h6>
        </div>
    </div>
</div>

Die itemtemplate wird für beliebige ListView-Elemente verwendet. Die ListView-Elemente können abhängig vom Kontext eine Gruppe oder einzelne Datenelemente sein. In der Datei "items.html" handelt es sich bei den ListView-Elementen beispielsweise um Gruppen.

Wichtig  Vorlagen, die Sie mithilfe der WinJS.Binding.Template erstellen, sind nicht mit Visual Studio-Projekt- und Elementvorlagen verbunden, z. B. "Grid" und "Split".

 

Von Projektvorlagen wird erwartet, dass in den Daten bestimmte Eigenschaften enthalten sind, die im HTML-Code explizit benannt sind. Der obige HTML-Code für itemtemplate enthält Eigenschaften wie title und subtitle. Wenn Ihre benutzerdefinierten App-Daten diese Eigenschaftennamen nicht verwenden, müssen Sie eine der folgenden Vorgehensweisen wählen:

  • Weisen Sie Ihre Daten diesen Eigenschaftennamen zu (i. d. R. in der Datei "data.js") oder
  • Korrigieren Sie alle im Vorlagencode enthaltenen Verweise auf diese Eigenschaften im HTML- und .js-Code, damit diese den Eigenschaftennamen entsprechen, die in Ihrem Code verwendet werden. In den Vorlagen werden folgende Eigenschaften verwendet:
    • title, subtitle, description und backgroundImage (Gruppen- und Elementeigenschaften)
    • group und content (Elementeigenschaften)
    • key (Gruppeneigenschaft)

Demselben WinJS-Vorlagenmuster folgend verwendet die Vorlage "Grid App" in einigen HTML-Seiten auch eine headerTemplate.

Beispiel für das Binden von Daten an die UI in den Vorlagen "Hub/Pivot", "Hub" und "Pivot"

In Visual Studio veranschaulichen die Projektvorlagen "Hub/Pivot", "Hub" und "Pivot", wie zwei unterschiedliche Datenquellen implementiert werden:

  • Globalisierte statische Daten, die in RESJSON-Ressourcendateien gespeichert werden. Diese Daten werden in einigen Steuerelementen der App-Abschnitte (PivotItem oder HubSection) verwendet.
  • Beispieldaten in data.js, die das Datenmodell darstellt. Diese Datei ist dieselbe Datei in den Rastervorlagen und den geteilten Vorlagen. Die Beispieldaten werden im ListView-Steuerelement in einem der App-Abschnitte verwendet.

Für den ersten Abruf von Beispieldaten werden deklarative Funktionen in der HTML verwendet, und das Datenmodell ist standardmäßig synchron. Um die Vorlagen so anzupassen, dass in sämtlichen Abschnitten dynamische Daten verwendet werden, müssen einige Änderungen in "hub.html", "hub.js" und anderen Dateien vorgenommen werden. Die folgenden Beispiel-Apps veranschaulichen die Anpassung der Vorlagen"Hub/Pivot" und"Hub" zur Unterstützung asynchroner Daten:

Da die globalisierten Daten in der RESJSON-Datei leicht ersetzt werden, lässt die Beispiel-App diese Ressourcendatei unverändert. In den Beispiel-Apps werden Daten für die <img>-Elemente und das ListView-Steuerelement in den Hub/Pivot-Abschnitten asynchron abgerufen.

Weitere Informationen zum Bereitstellen globalisierter Daten in RESJSON-Dateien finden Sie unter Schnellstart: Übersetzen von UI-Ressourcen.

Wenn Sie das Binden von asynchronen Daten an das ListView-Steuerelement von Hub/Pivot unterstützen möchten, müssen Sie zuerst diese globalen Variablen in "hub.js" ersetzen, mit denen das Datenmodell aufgerufen wird.

var section3Group = Data.resolveGroupReference("group4");
var section3Items = Data.getItemsFromGroup(section3Group);

Durch diese Variablendeklarationen:


var section3Group = "group2";
var section3Items;

Außerdem muss die Implementierung der deklarativen Funktionen in hub.js geändert werden. In der Standardvorlagenimplementierung hängen diese Funktionen von den Daten ab, die bereits verfügbar sind (z. B. der Aufruf von section3Items.dataSource). Ersetzen Sie diesen Code:

section3DataSource: section3Items.dataSource,

section3HeaderNavigate: util.markSupportedForProcessing(function (args) {
    nav.navigate("/pages/section/section.html", { title: args.detail.section.header, 
        groupKey: section3Group.key });
}),

section3ItemNavigate: util.markSupportedForProcessing(function (args) {
    var item = Data.getItemReference(section3Items.getAt(args.detail.itemIndex));
    nav.navigate("/pages/item/item.html", { item: item });
}),

durch diese Codezeile:


section3DataSource: null,

section3HeaderNavigate: util.markSupportedForProcessing(function (args) {
    nav.navigate("/pages/section/section.html", { title: args.detail.section.header,
        groupKey: section3Group });
}),

section3ItemNavigate: util.markSupportedForProcessing(function (args) {
    var itemSet = section3Items;
    var itemObj = itemSet.getAt(args.detail.itemIndex);
    var item = [itemObj.group.key, itemObj.title, itemObj.backgroundImage];

    nav.navigate("/pages/item/item.html", { item: item });
}),

Der Code legt die section3DataSource-Funktion auf Null fest, damit keine unfertigen Daten gebunden werden können. Wir legen die Datenquelle später in einer Datenbindungsfunktion (je nach Beispiel-App in _bindData oder bindListView) fest.

Die Datenbindungsfunktion wird aufgerufen, sobald die Daten verfügbar sind. Dazu fügen wir einen Listener für das dataReady-Ereignis des Datenmodells hinzu, das in der Beispiel-App in "data.js" definiert ist.


this._observer = Data.getObservable();
this._observer.addEventListener('dataReady', this.onDataCompleted.bind(this));

Die App ruft die Datenbindungsfunktion aus dem onDataCompleted-Ereignishandler auf (nicht dargestellt). Der Code für die _bindData-Funktion des Beispiels für die Vorlage"Hub" ist hier angegeben. In diesem Code legen wir die itemDataSource-Eigenschaft des ListView-Steuerelements fest.


_bindData: function (context, grp1Items, grp2Items) {

    var self = context;

    // . . .

    self._items = grp2Items;
    section3Items = self._items;
    self._section3lv.itemDataSource = self._items.dataSource;

    // . . .   

},

Wenn die Schaltfläche "Zurück" zum Navigieren auf die Seite verwendet wird, wird die Datenbindungsfunktion direkt aus der Initialisierungsfunktion der Seite aufgerufen, da es nicht erforderlich ist, auf neue Daten zu warten.

Tipp  Zum Abfragen des DOM für das ListView-Element (in _section3lv gespeichert) im Hub-Vorlagencode ruft die App eine _hubReady-Funktion aus dem loadingstatechanged-Ereignishandler des Hub-Steuerelements auf. Dieses Ereignis wird nur aktiviert, wenn das Laden der Hubseite abgeschlossen wurde. Mithilfe dieses Ereignishandlers können wir das DOM abfragen, um das geschachtelte DIV-Element abzurufen, das dem ListView-Steuerelement zugeordnet ist.

 

Den vollständigen Code, der dafür sorgt, dass die asynchronen Daten in den Vorlagen "Hub/Pivot" und "Hub" verwendet werden können, finden Sie unter JSON-Web-Reader, der die Vorlage "Hub/Pivot" verwendet und JSON-Web-Reader, der die Vorlage "Hub" verwendet. Zusätzlich zu den hier beschriebenen Anpassungen haben wir an der Beispiel-App die folgenden Änderungen vorgenommen:

  • In das Datenmodell (data.js) wurde Code zum Abrufen von Daten mit einer xhr-Anforderung und zum Analysieren von JSON-Daten (aus Flickr) eingefügt.
  • In das Datenmodell wurde Code zum Behandeln mehrerer Datenanforderungen und zum Aktivieren des dataReady-Ereignisses bei der Rückgabe von Daten eingefügt.
  • In die UI wurde ein Eingabefeld zum Anfordern neuer Daten eingefügt.
  • Es wurde eine Statusleiste eingefügt, in der der Status der Datenanforderung angezeigt werden kann.
  • CSS-Formatvorlagen für das Eingabefeld und die Statusleiste wurden hinzugefügt.
  • Funktionen zum Initialisieren der Seite nach dem vollständigen Laden des Hub-Steuerelements wurden eingefügt (z. B. _hubReady oder _hubReadyPhone).
  • Die <img>-Elemente von "Hub/Pivot" und "Hub" wurden so geändert, dass sie Klickereignisse unterstützen (geänderte Dateien sind vorlagenspezifisch).
  • Dateien wurden so geändert, dass sie asynchrone Daten an die <img>-Elemente von "Hub/Pivot" und "Hub" binden (geänderte Dateien sind vorlagenspezifisch).
  • "hub.js" wurde so geändert, dass die Navigation zu Bildern von den <img>-Elementen von "Hub" unterstützt wird (geänderte Dateien sind vorlagenspezifisch).
  • "item.html" und "item.js" wurden geändert, um das Anzeigen einzelner Bilder zu unterstützen.

Beispiel für das Binden von Daten an die UI ("Grid" und "Split")

In diesem Abschnitt wird gezeigt, wie Sie in den Vorlagen "Grid" und "Split" eine eigene Datenquelle implementieren. Der Beispielcode verwendet eine xhr-Anforderung zum Generieren der RSS-Daten.

Wichtig  Wie asynchrone Daten in der Vorlage "Hub" implementiert werden, ist im Abschnitt Binden von Daten an die UI in der Vorlage "Hub" beschrieben.

 

Aktualisieren von "data.js"

  1. Erstellen Sie in Visual Studio ein neues Projekt. Verwenden Sie entweder die Projektvorlage "Split App" oder "Grid App".

  2. Fügen Sie die folgenden Variablen in "data.js" am Dateianfang und nach der Anweisung use strict hinzu:

    var lightGray = "data:image/png;base64,
        iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXY7h4+cp/AAhpA3h+ANDKAAAAAElFTkSuQmCC";
    var mediumGray = "data:image/png;base64,
        iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXY5g8dcZ/AAY/AsAlWFQ+AAAAAElFTkSuQmCC";
    
  3. Entfernen Sie die Funktion generateSampleData mit den nachstehenden Arrays aus "data.js": sampleGroups und sampleItems.

    Wir ersetzen diese Daten durch RSS-Daten. Wir werden auch die meisten Platzhaltervariablen wie groupDescription nicht verwenden. Damit dieser Code funktioniert, müssen wir jedoch die Platzhalterbilder (lightGray und mediumGray) wiederverwenden.

  4. Fügen Sie an der gleichen Position, an der Sie generateSampleData entfernt haben, den folgenden Code zu data.js hinzu:

    
    function getFeeds() {
        // Create an object for each feed.
        blogs = [
            {
                key: "blog1", url: 
           'https://windowsteamblog.com/windows/b/developers/atom.aspx',
                title: 'tbd', subtitle: 'subtitle', updated: 'tbd',
                backgroundImage: lightGray,
                acquireSyndication: acquireSyndication, dataPromise: null
            },
            {
                key: "blog2", url: 
           'https://windowsteamblog.com/windows/b/windowsexperience/atom.aspx',
                title: 'tbd', subtitle: 'subtitle', updated: 'tbd',
                backgroundImage: lightGray,
                acquireSyndication: acquireSyndication, dataPromise: null
            }]
        // Get the content for each feed in the blog's array.
        blogs.forEach(function (feed) {
            feed.dataPromise = feed.acquireSyndication(feed.url);
            dataPromises.push(feed.dataPromise);
        });
    
        // Return when all asynchronous operations are complete
        return WinJS.Promise.join(dataPromises).then(function () {
            return blogs;
        });
    
    };
    
    function acquireSyndication(url) {
        return WinJS.xhr(
        {
            url: url,
            headers: { "If-Modified-Since": "Mon, 27 Mar 1972 00:00:00 GMT" }               
        });
    }
    
    function getBlogPosts() {
        getFeeds().then(function () {
            // Process each blog.
            blogs.forEach(function (feed) {
                feed.dataPromise.then(function (articlesResponse) {
                    var articleSyndication = articlesResponse.responseXML;
    
                    // Get the blog title and last updated date.
                    if (articleSyndication) {
                        // Get the blog title and last updated date.
                        feed.title = articleSyndication.querySelector(
                            "feed > title").textContent;
                        var ds = articleSyndication.querySelector(
                            "feed > updated").textContent;
                        var date = ds.substring(5, 7) + "-" +
                            ds.substring(8, 10) + "-" + ds.substring(0, 4);
                        feed.updated = "Last updated " + date;
                        // Process the blog posts.
                        getItemsFromXml(articleSyndication, blogPosts, feed);
                    }
                    else {
                        // There was an error loading the blog. 
                        feed.title = "Error loading blog";
                        feed.updated = "Error";
                        blogPosts.push({
                            group: feed,
                            key: "Error loading blog",
                            title: feed.url,
                            author: "Unknown",
                            month: "?",
                            day: "?",
                            year: "?",
                            content: "Unable to load the blog at " + feed.url
                        });
                    }
                });
            });
        });
    
        return blogPosts;
    }
    
    function getItemsFromXml(articleSyndication, blogPosts, feed) {
        var posts = articleSyndication.querySelectorAll("entry");
        // Process each blog post.
        for (var postIndex = 0; postIndex < posts.length; postIndex++) {
            var post = posts[postIndex];
            // Get the title, author, and date published.
            var postTitle = post.querySelector("title").textContent;
            var postAuthor = post.querySelector("author > name").textContent;
            var pds = post.querySelector("published").textContent;
            var postDate = pds.substring(5, 7) + "-" + pds.substring(8, 10)
                + "-" + pds.substring(0, 4);
            // Process the content so that it displays nicely.
            var staticContent = toStaticHTML(post.querySelector(
                "content").textContent);
            // Store the post info we care about in the array.
            blogPosts.push({
                group: feed, key: feed.title, title: postTitle, 
                author: postAuthor, pubDate: postDate, 
                backgroundImage: mediumGray, content: staticContent
            });
        }
    }
    
  5. Ersetzen Sie in data.js folgenden Code:

    var list = new WinJS.Binding.List();
    var groupedItems = list.createGrouped(
        function groupKeySelector(item) { return item.group.key; },
        function groupDataSelector(item) { return item.group; }
    );
    
    // TODO: Replace the data with your real data.
    // You can add data from asynchronous sources whenever it becomes available.
    generateSampleData.forEach(function (item) {
        list.push(item);
    });
    

    durch diese Codezeile:

    var dataPromises = [];
    var blogs;
    
    var blogPosts = new WinJS.Binding.List();
    
    var list = getBlogPosts();
    var groupedItems = list.createGrouped(
        function groupKeySelector(item) { return item.group.key; },
        function groupDataSelector(item) { return item.group; }
    );
    

    Auch der Code in createGrouped, der die Gruppierung angibt (die Funktionen groupKeySelector und groupDataSelector) wird wiederverwendet.

    Da wir einige der von der Vorlage erwarteten Eigenschaftennamen geändert haben, müssen wir an den HTML-Seiten einige Aktualisierungen vornehmen. Insbesondere müssen wir für alle subtitle-Eigenschaften, die auf ein Element (keine Gruppe) verweisen, subtitle in author ändern. Für alle description-Eigenschaften, die auf ein Element verweisen, müssen wir description in pubDate ändern.

    In den folgenden Abschnitten finden Sie Informationen darüber, wie Sie diese Änderungen in der UI implementieren:

    • Binden von Beispieldaten an die UI in der Vorlage "Split"
    • Binden von Beispieldaten an die UI in der Vorlage "Grid"

Binden von Beispieldaten an die UI in der Vorlage "Split"

  1. Öffnen Sie split.html, um die Beispieldaten in der Vorlage "Split" zu verwenden.

  2. In split.html müssen wir einige Zeilen im DIV-Element ändern, das den Klassennamen itemtemplate aufweist. Ändern Sie diese Zeile:

    
    <h6 class="item-subtitle win-type-ellipsis" data-win-bind="textContent: subtitle"></h6>
    

    in:

    <h6 class="item-subtitle win-type-ellipsis" data-win-bind="textContent: author"></h6>
    
  3. Auch in split.html enthält der Elementabschnitt (articlesection) Kopfzeileninformationen, die aktualisiert werden müssen. Ändern Sie diese Zeile:

    <h4 class="article-subtitle" data-win-bind="textContent: subtitle"></h4>
    

    in:

    <h4 class="article-subtitle" data-win-bind="textContent: author"></h4>
    
  4. Öffnen Sie items.html.

    Die im HTML-Code definierte WinJS-Elementvorlage enthält beliebige ListView-Elemente. In items.html wird die Vorlage zum Anzeigen von Gruppen (Blogs) verwendet. Hier müssen wir lediglich die Gruppeneigenschaft subtitle ändern.

    <h6 class="item-subtitle win-type-ellipsis" 
        data-win-bind="textContent: subtitle"></h6>
    
  5. Ändern Sie die subtitle-Eigenschaft in updated, so wie hier gezeigt:

    <h6 class="item-subtitle win-type-ellipsis"
        data-win-bind="textContent: updated"></h6>
    
  6. Speichern Sie das Projekt, und drücken Sie dann F5, um die App zu debuggen.

    Der Seitentitel wird sofort angezeigt, aber beim Abrufen der Feeddaten gibt es eine kurze Verzögerung. Wenn alles geklappt hat, sehen Sie auf der Startseite alle Blogs. Klicken Sie auf einen Blog, um Beiträge in der Master/Details-Ansicht anzuzeigen.

Binden von Beispieldaten an die UI in der Vorlage "Grid"

Aktualisieren Sie vor dem Ausführen dieser Schritte die Projektdatei "data.js", wie unter Beispiel für das Binden von Daten an die UI beschrieben.

  1. Öffnen Sie groupDetail.html, um die Beispieldaten in der Vorlage "Grid" zu verwenden.

    Diese Seite enthält eine einzige Gruppe (einen Blog) sowie einzelne Elemente (Blogbeiträge), die zu der Gruppe gehören.

  2. In groupDetail.html müssen wir einige Zeilen im DIV-Element ändern, das den Klassennamen item-info aufweist. Ändern Sie folgende Zeilen:

    
    <h6 class="item-subtitle win-type-ellipsis"
        data-win-bind="textContent: subtitle"></h6>
    <h4 class="item-description" 
        data-win-bind="textContent: description"></h4>
    

    In Folgendes:

    <h6 class="item-subtitle win-type-ellipsis" 
        data-win-bind="textContent: author"></h6>
    <h4 class="item-description" 
        data-win-bind="textContent: pubDate"></h4>
    

    In groupDetail.html beschreibt die Kopfzeilenvorlage Gruppeninformationen und keine einzelnen Elemente. Daher müssen wir die subtitle-Eigenschaft nicht ändern. Dies ist die Kopfzeilenvorlage:

    
    <div class="headertemplate" data-win-control="WinJS.Binding.Template">
        <h2 class="group-subtitle" data-win-bind="textContent: subtitle"></h2>
        <img class="group-image" src="#" 
            data-win-bind="src: backgroundImage; alt: title" />
        <h4 class="group-description" data-win-bind="innerHTML: description"></h4>
    </div>
    
  3. Wir haben jedoch keine description-Eigenschaft für jede Gruppe (sie ist für Elemente vorhanden). Daher müssen wir diese Eigenschaft im obigen Code wie folgt in updated ändern:

    <h4 class="group-description" data-win-bind="innerHTML: updated"></h4>
    
  4. Öffnen Sie die Datei "groupedItems.html". Dort werden alle Gruppen mit den zugehörigen Blogbeiträgen angezeigt.

  5. Auf dieser Seite zeigt die generische WinJS-Elementvorlage einzelne Elemente (Blogbeiträge) an. Daher müssen wir die subtitle-Eigenschaft aktualisieren. Ändern Sie Folgendes:

    <h6 class="item-subtitle win-type-ellipsis" 
        data-win-bind="textContent: subtitle"></h6>
    

    in:

    <h6 class="item-subtitle win-type-ellipsis" 
        data-win-bind="textContent: author"></h6>
    
  6. Speichern Sie das Projekt, und drücken Sie dann F5, um die App zu debuggen.

    Der Seitentitel wird sofort angezeigt, aber beim Abrufen der Feeddaten gibt es eine kurze Verzögerung. Wenn die Daten zurückgegeben werden und die Zusagen erfüllt wurden, sehen Sie auf der Startseite die in jedem Blog enthaltenen Elemente. Klicken Sie auf eine Gruppenüberschrift, um die Gruppenseite anzuzeigen, oder auf ein Element, um einen Blogbeitrag zu lesen.

Code für "data.js"

Im Folgenden sehen Sie den vollständigen Code für "data.js". Für die Beispiele mit den Vorlagen "Raster-App" und "Geteilte App" wird die gleiche Datei "data.js" verwendet. Informationen zur Datei „data.js“ für die Vorlage „Hub/Pivot“ finden Sie unter JSON-Web-Reader, der die Vorlage „Hub/Pivot“ verwendet. Informationen zur Datei „data.js“ für die Vorlage „Hub“ finden Sie unter JSON-Web-Reader, der die Vorlage „Hub“ verwendet.


(function () {
    "use strict";

    
    var lightGray = "data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXY7h4+cp/AAhpA3h+ANDKAAAAAElFTkSuQmCC";
    var mediumGray = "data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXY5g8dcZ/AAY/AsAlWFQ+AAAAAElFTkSuQmCC";


    var dataPromises = [];
    var blogs;

    var blogPosts = new WinJS.Binding.List();

    var list = getBlogPosts();
    var groupedItems = list.createGrouped(
        function groupKeySelector(item) { return item.group.key; },
        function groupDataSelector(item) { return item.group; }
    );

    WinJS.Namespace.define("Data", {
        items: groupedItems,
        groups: groupedItems.groups,
        getItemReference: getItemReference,
        getItemsFromGroup: getItemsFromGroup,
        resolveGroupReference: resolveGroupReference,
        resolveItemReference: resolveItemReference
    });

    // Get a reference for an item, using the group key and item title as a
    // unique reference to the item that can be easily serialized.
    function getItemReference(item) {
        return [item.group.key, item.title];
    }

    // This function returns a WinJS.Binding.List containing only the items
    // that belong to the provided group.
    function getItemsFromGroup(group) {
        return list.createFiltered(function (item) { return item.group.key === group.key; });
    }

    // Get the unique group corresponding to the provided group key.
    function resolveGroupReference(key) {
        return groupedItems.groups.getItemFromKey(key).data;
    }

    // Get a unique item from the provided string array, which should contain a
    // group key and an item title.
    function resolveItemReference(reference) {
        for (var i = 0; i < groupedItems.length; i++) {
            var item = groupedItems.getAt(i);
            if (item.group.key === reference[0] && item.title === reference[1]) {
                return item;
            }
        }
    }



    function getFeeds() {
        // Create an object for each feed.
        blogs = [
            {
                key: "blog1", url:
           'https://windowsteamblog.com/windows/b/developers/atom.aspx',
                title: 'tbd', subtitle: 'subtitle', updated: 'tbd',
                backgroundImage: lightGray,
                acquireSyndication: acquireSyndication, dataPromise: null
            },
            {
                key: "blog2", url:
           'https://windowsteamblog.com/windows/b/windowsexperience/atom.aspx',
                title: 'tbd', subtitle: 'subtitle', updated: 'tbd',
                backgroundImage: lightGray,
                acquireSyndication: acquireSyndication, dataPromise: null
            }]
        // Get the content for each feed in the blog's array.
        blogs.forEach(function (feed) {
            feed.dataPromise = feed.acquireSyndication(feed.url);
            dataPromises.push(feed.dataPromise);
        });

        // Return when all asynchronous operations are complete
        return WinJS.Promise.join(dataPromises).then(function () {
            return blogs;
        });

    };

    function acquireSyndication(url) {
        return WinJS.xhr({
            url: url,
            headers: { "If-Modified-Since": "Mon, 27 Mar 1972 00:00:00 GMT" }
        });
    }

    function getBlogPosts() {
        getFeeds().then(function () {
            // Process each blog.
            blogs.forEach(function (feed) {
                feed.dataPromise.then(function (articlesResponse) {
                    var articleSyndication = articlesResponse.responseXML;

                    if (articleSyndication) {
                        // Get the blog title and last updated date.
                        feed.title = articleSyndication.querySelector(
                            "feed > title").textContent;
                        var ds = articleSyndication.querySelector(
                            "feed > updated").textContent;
                        var date = ds.substring(5, 7) + "-" +
                            ds.substring(8, 10) + "-" + ds.substring(0, 4);
                        feed.updated = "Last updated " + date;
                        // Process the blog posts.
                        getItemsFromXml(articleSyndication, blogPosts, feed);
                    }
                    else {
                        // There was an error loading the blog. 
                        feed.title = "Error loading blog";
                        feed.updated = "Error";
                        blogPosts.push({
                            group: feed,
                            key: "Error loading blog",
                            title: feed.url,
                            author: "Unknown",
                            month: "?",
                            day: "?",
                            year: "?",
                            content: "Unable to load the blog at " + feed.url
                        });
                    }
                });
            });
        });

        return blogPosts;
    }

    function getItemsFromXml(articleSyndication, blogPosts, feed) {
        var posts = articleSyndication.querySelectorAll("entry");
        // Process each blog post.
        for (var postIndex = 0; postIndex < posts.length; postIndex++) {
            var post = posts[postIndex];
            // Get the title, author, and date published.
            var postTitle = post.querySelector("title").textContent;
            var postAuthor = post.querySelector("author > name").textContent;
            var pds = post.querySelector("published").textContent;
            var postDate = pds.substring(5, 7) + "-" + pds.substring(8, 10)
                + "-" + pds.substring(0, 4);
            // Process the content so that it displays nicely.
            var staticContent = toStaticHTML(post.querySelector(
                "content").textContent);
            // Store the post info we care about in the array.
            blogPosts.push({
                group: feed, key: feed.title, title: postTitle,
                author: postAuthor, pubDate: postDate,
                backgroundImage: mediumGray, content: staticContent
            });
        }
    }

})();

Verwandte Themen

JavaScript-Projektvorlagen

JavaScript-Elementvorlagen

Hinzufügen von Daten zu einer Projektvorlage (mit C#/VB und C++)