Come personalizzare dati di modelli di Visual Studio (HTML)

[ Questo articolo è rivolto agli sviluppatori per Windows 8.x e Windows Phone 8.x che realizzano app di Windows Runtime. Gli sviluppatori che usano Windows 10 possono vedere Documentazione aggiornata ]

Nei modelli Hub/Pivot, Hub, Pivot, Grid e Split il codice che ottiene i dati necessari per l'app è nel file data.js. Questo file rappresenta un'origine dati di esempio per l'app. Il file data.js include dati statici che di solito devono essere sostituiti con dati dinamici. Se ad esempio l'app effettua una singola richiesta xhr per ottenere dati RSS o JSON, devi in genere includere questo codice in data.js. In questo modo potrai usare facilmente i tuoi dati senza cambiare il modello di dati presente nei modelli.

Suggerimento  I modelli Hub/Pivot, Hub e Pivot recuperano anche dati statici dai file resjson che supportano la globalizzazione. Per altre info, vedi Esempio di binding dei dati all'interfaccia utente nei modelli Hub/Pivot, Hub e Pivot.

 

Quando aggiungi dati personali a un'app, devi fare attenzione ad alcuni aspetti:

  • Gruppi ed elementi sono collegati in modo intrinseco. L'app prevede che i dati degli elementi siano organizzati in gruppi. Puoi scollegare le due entità nella tua implementazione, ma affinché l'implementazione funzioni devi modificare il codice. In questo argomento viene illustrato l'utilizzo dei gruppi nel modello di dati.
  • Quando implementi dati personalizzati per un'app in data.js, devi accertarti che i nomi di proprietà inerenti ai dati personalizzati siano mappati ai nomi di proprietà usati dal modello. Puoi modificare i nomi usati dal modello, ma questa operazione richiede un'altra revisione del codice. In questo argomento troverai alcuni esempi di come fare.

Elementi e gruppi

I dati dei modelli sono archiviati in un elemento WinJS.Binding.List. Questo codice mostra la dichiarazione di un elenco nel file data.js.

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

Una matrice di dati degli elementi (in questo esempio sampleItems) viene passata a WinJS.Binding.List dalla funzione push, in questo modo:

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

WinJS.Binding.List include la logica interna per la gestione dei raggruppamenti di dati. La matrice sampleItems include una proprietà group che identifica il gruppo a cui appartiene l'elemento (nei dati di esempio i gruppi sono specificati nella matrice sampleGroups). Ecco la matrice di dati nella funzione generateSampleData:

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

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

    return sampleItems;
}

Quando modifichi l'app per i dati personalizzati, puoi seguire lo stesso schema per il raggruppamento dei dati. Per set di dati più piccoli, è consigliabile usare WinJS.Binding.List per ListView. Se non raggruppi gli elementi, puoi comunque usare WinJS.Binding.List, ma devi modificare il codice del modello nei punti in cui il modello prevede di trovare dati basati sui gruppi.

Suggerimento  WinJS.Binding.List è un'origine dati sincrona che usa una matrice JavaScript. Per set di dati molto grandi, ad esempio con migliaia di elementi, può essere necessario usare un'origine dati asincrona. Per ulteriori informazioni, vedi Uso ListView.

 

La funzione createGrouped di WinJS.Binding.List specifica come raggruppare gli elementi usando una chiave di gruppo e un valore del gruppo di elementi. Questa funzione viene chiamata in data.js. key e group sono entrambi nomi di proprietà specificati nelle matrici di dati di esempio.

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

Quando l'app del modello necessita di un elenco di elementi, chiama getItemsFromGroup, che restituisce un elemento WinJS.Binding.List contenente solo gli elementi che appartengono al gruppo specificato.

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

Suggerimento  Funzioni come getItemsFromGroup, che chiamano createFiltered, creano un nuovo progetto di WinJS.Binding.List e potrebbe essere necessario eliminare l'oggetto restituito se esci dalla pagina. Per eliminare l'oggetto, chiama il metodo WinJS.Binding.List.dispose.

 

La funzione define della Libreria di Windows per JavaScript espone i dati per l'uso nell'app specificando uno spazio dei nomi denominato Data insieme a un set di funzioni membro pubblico.

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

Se vuoi definire un'origine dati diversa per ogni pagina dell'app, oppure un modello di dati diverso, dovrai sostituire tutte le chiamate a questi membri nel codice JavaScript.

Associazione di dati di elementi e gruppi all'interfaccia utente

Il codice seguente mostra un esempio di markup per il controllo ListView. L'origine dati per ListView è specificata nella proprietà itemDataSource, illustrata qui. L'esempio proviene da split.html nel modello 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>

Nel codice precedete, una proprietà itemDataSource associata alla pagina è stata assegnata alla proprietà itemDataSource del controllo ListView.

Nei modelli i dati sono in genere associati all'interfaccia utente nella funzione init o nella funzione ready, definita nel file con estensione js associato a ogni pagina HTML. Il codice seguente è contenuto nella funzione init per split.html. In questo codice l'app ottiene un riferimento a un gruppo e quindi chiama getItemsFromGroup, implementato in data.js. Come abbiamo detto in precedenza, getItemsFromGroup restituisce un elemento WinJS.Binding.List che contiene solo gli elementi inclusi nel gruppo specificato.

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

Associamo quindi l'elenco restituito da getItemsFromGroup alla proprietà itemDataSource della pagina, che associa i dati a ListView, e specifichiamo inoltre il gestore per la selezione di elementi (_selectionChanged).


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

Per visualizzare ogni elemento in ListView, l'app associa un modello a ListView, come illustrato qui. Il codice viene visualizzato nel markup per il controllo ListView e usa la proprietà itemTemplate per specificare un elemento DIV con nome di classe itemtemplate.

itemTemplate: select('.itemtemplate')

I modelli WinJS, basati su WinJS.Binding.Template, vengono usati per formattare e visualizzare istanze multiple di dati. Il modello più comune usato nei modelli Grid e Split è il modello di elemento usato per visualizzare gli elementi in ListView. Come ogni oggetto modello WinJS, per dichiararlo devi aggiungere un attributo data-win-control e impostare l'attributo su WinJS.Binding.Template. Ecco il codice HTML per 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>

L'elemento itemtemplate viene usato per elementi ListView arbitrari. Gli elementi ListView possono essere gruppi o singoli elementi di dati, a seconda del contesto. In items.html, ad esempio, gli elementi ListView sono gruppi.

Importante  I modelli creati usando WinJS.Binding.Template non sono correlati a modelli di elemento e di progetto di Visual Studio, come Applicazione griglia e Applicazione divisa.

 

I modelli di progetto prevedono la presenza di determinate proprietà nei dati e queste proprietà sono denominate in modo esplicito nel codice HTML. Nel codice HTML precedente per itemtemplate puoi trovare proprietà come title e subtitle. Se i dati personalizzati della tua app non usano questi nomi di proprietà, dovrai eseguire una delle operazioni seguenti:

  • Mappare i dati a questi nomi di proprietà (in genere in data.js), oppure
  • Correggere tutti i riferimenti di codice HTML e con estensione js impostando queste proprietà nel codice del modello, in modo che corrispondano ai nomi di proprietà usati nei dati. Le proprietà usate nei modelli includono:
    • title, subtitle, description e backgroundImage (proprietà di gruppi ed elementi)
    • group e content (proprietà di elementi)
    • key (proprietà di gruppi)

In base allo stesso schema del modello WinJS, anche il modello Applicazione griglia usa un elemento headerTemplate in alcune pagine HTML.

Esempio di binding dei dati all'interfaccia utente nei modelli Hub/Pivot, Hub e Pivot

In Visual Studio i modelli di progetto Hub/Pivot, Hub e Pivot dimostrano come implementare due diverse origini dati:

  • Dati statici globalizzati archiviati nei file di risorse resjson. Questi dati vengono usati in alcuni controlli delle sezioni dell'app (PivotItem o HubSection).
  • Dati di esempio in data.js, che rappresentano il modello di dati. Questo file è lo stesso dei modelli Grid e Split. I dati di esempio vengono usati nel controllo ListView in una delle sezioni dell'app.

Le funzioni dichiarative nel codice HTML vengono usate per ottenere inizialmente i dati di esempio. Il modello di dati è sincrono per impostazione predefinita. Per personalizzare i modelli in modo che usino dati dinamici in tutte le sezioni, è necessario apportare alcune modifiche ai file hub.html, hub.js e ad altri file. Le app di esempio seguenti mostrano come personalizzare i modelli Hub/Pivot e Hub per supportare i dati asincroni:

Poiché i dati globalizzati nel file resjson sono facilmente sostituibili, le app di esempio lasciano questo file di risorse invariato. Nelle app di esempio i dati per gli elementi <img> e il controllo ListView presenti nelle sezioni di Hub/Pivot vengono recuperati in modo asincrono.

Per altre informazioni su come fornire dati globalizzati nei file resjson, vedi Guida introduttiva: Traduzione delle risorse dell'interfaccia utente

Per supportare il binding di dati asincroni al controllo ListView di Hub/Pivot, sostituisci innanzitutto in hub.js queste variabili globali che chiamano il modello di dati:

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

con queste dichiarazioni variabili:


var section3Group = "group2";
var section3Items;

Devi inoltre modificare l'implementazione delle funzioni dichiarative in hub.js. Nell'implementazione predefinita del modello queste funzioni dipendono dai dati già disponibili (ad esempio la chiamata a section3Items.dataSource). Sostituisci questo codice:

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 });
}),

con questo:


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 });
}),

Questo codice imposta la funzione section3DataSource su Null, per evitare che venga eseguito un tentativo di binding dei dati prima che questi siano pronti. Successivamente imposteremo l'origine dati in una funzione di data binding (_bindData o bindListView, in base all'app di esempio).

La funzione di data binding viene chiamata quando i dati sono disponibili. Per consentire questa operazione, aggiungiamo un listener per l'evento del modello di dati dataReady, definito nell'app di esempio in data.js.


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

L'app chiama la funzione di data binding dal gestore eventi onDataCompleted (non illustrato). Il codice per la funzione _bindData dell'esempio di modello Hub è illustrato qui. In questo codice impostiamo la proprietà itemDataSource di ListView.


_bindData: function (context, grp1Items, grp2Items) {

    var self = context;

    // . . .

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

    // . . .   

},

Se per passare alla pagina viene usato il pulsante Indietro, la funzione di data binding viene chiamata direttamente dalla funzione di inizializzazione della pagina, perché non è necessario attendere nuovi dati.

Suggerimento  Nel codice del modello Hub, per eseguire una query sul modello DOM per l'elemento ListView (archiviato in _section3lv), l'app chiama una funzione _hubReady dal gestore dell'evento loadingstatechanged del controllo Hub. Questo evento si attiva solo dopo che il caricamento della pagina hub è stato completato. Usando questo gestore eventi possiamo fare una query sul modello DOM per ottenere l'elemento DIV annidato associato a ListView.

 

Il codice completo per fare in modo che i dati asincroni funzionino nei modelli Hub/Pivot e Hub è disponibile nel lettore Web JSON che usa il modello Hub/Pivot e nel lettore Web JSON che usa il modello Hub. Oltre alle personalizzazioni illustrate qui, abbiamo apportato le modifiche seguenti all'app di esempio:

  • Inserimento di codice nel modello di dati (data.js) per il recupero dei dati tramite una richiesta xhr e l'analisi dei dati JSON (da Flickr).
  • Inserimento di codice nel modello di dati per la gestione di richieste di dati multiple e l'attivazione dell'evento dataReady quando i dati vengono restituiti.
  • Inserimento di una casella di input nell'interfaccia utente per la richiesta di nuovi dati.
  • Inserimento di una barra di stato per mostrare lo stato della richiesta di dati.
  • Aggiunta di stile CSS per la casella di input e la barra di stato.
  • Inserimento di funzioni per l'inizializzazione della pagina dopo il caricamento completo del controllo Hub, ad esempio _hubReady o _hubReadyPhone.
  • Modifica degli elementi <img> di Hub/Pivot o Hub per il supporto degli eventi clic (i file modificati sono specifici del modello).
  • Modifica dei file per il binding dei dati asincroni agli elementi <img> di Hub/Pivot o Hub (i file modificati sono specifici del modello).
  • Modifica di hub.js per il supporto del passaggio alle immagini dagli elementi <img> di Hub (i file modificati sono specifici del modello).
  • Modifica di item.html e item.js per il supporto della visualizzazione di immagini singole.

Esempio di associazione dei dati all'interfaccia utente (Grid e Split)

Questa sezione mostra come implementare un'origine dati personalizzata nei modelli di progetto Grid e Split. Il codice di esempio usa una richiesta xhr per generare dati RSS.

Importante  Per l'implementazione di dati asincroni nel modello Hub, vedi Binding dei dati con l'interfaccia utente nel modello Hub.

 

Aggiornamento di data.js

  1. Creare un nuovo progetto in Visual Studio. Usa il modello di progetto Applicazione divisa o Applicazione griglia.

  2. In data.js aggiungi le variabili seguenti quasi all'inizio del file, dopo l'istruzione use strict:

    var lightGray = "data:image/png;base64,
        iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXY7h4+cp/AAhpA3h+ANDKAAAAAElFTkSuQmCC";
    var mediumGray = "data:image/png;base64,
        iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXY5g8dcZ/AAY/AsAlWFQ+AAAAAElFTkSuQmCC";
    
  3. In data.js rimuovi la funzione generateSampleData contenente le matrici sampleGroups e sampleItems.

    Sostituiremo questi dati con i dati RSS. Non useremo la maggior parte delle variabili segnaposto, come groupDescription, ma per garantire il funzionamento del nuovo codice riutilizzeremo le immagini segnaposto lightGray e mediumGray.

  4. Nella stessa posizione da cui hai rimosso generateSampleData, aggiungi il codice seguente a data.js:

    
    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. In data.js sostituisci questo codice:

    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);
    });
    

    con questo:

    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; }
    );
    

    Useremo di nuovo il codice in createGrouped che specifica il raggruppamento— delle funzioni groupKeySelector e groupDataSelector.

    Dato che abbiamo modificato alcuni dei nomi di proprietà previsti dal modello, dovremo apportare alcuni aggiornamenti nelle pagine HTML. In particolare, per tutte le proprietà subtitle che fanno riferimento a un elemento (non a un gruppo), dobbiamo modificare subtitle in author. Per le proprietà description che fanno riferimento a un elemento, dobbiamo modificare description in pubDate.

    Per implementare queste modifiche nell'interfaccia utente, vedi una delle sezioni seguenti:

    • Associazione di dati di esempio all'interfaccia utente nel modello Split
    • Associazione di dati di esempio all'interfaccia utente nel modello Grid

Associazione di dati di esempio all'interfaccia utente nel modello Split

  1. Per usare il codice di esempio nel modello Applicazione divisa, apri split.html.

  2. In split.html dobbiamo modificare alcune righe nell'elemento DIV con un nome di classe itemtemplate. Modifica questa riga:

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

    in queste:

    <h6 class="item-subtitle win-type-ellipsis" data-win-bind="textContent: author"></h6>
    
  3. Inoltre in split.html la sezione relativa all'articolo (articlesection) include informazioni di intestazione che devono essere aggiornate. Modifica questa riga:

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

    in queste:

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

    Il modello di elemento WinJS definito nel codice HTML contiene elementi ListView arbitrari. In items.html il modello è usato per mostrare i gruppi (blog). L'unica proprietà di gruppo che dobbiamo modificare qui è subtitle.

    <h6 class="item-subtitle win-type-ellipsis" 
        data-win-bind="textContent: subtitle"></h6>
    
  5. Modifica la proprietà subtitle in updated, come illustrato qui:

    <h6 class="item-subtitle win-type-ellipsis"
        data-win-bind="textContent: updated"></h6>
    
  6. Salva il progetto e premi F5 per eseguire il debug dell'app.

    Vedrai immediatamente il titolo della pagina, ma noterai un breve ritardo mentre vengono recuperati i dati del feed. Quando tutto sarà a posto, vedrai ogni blog nella home page. Fai clic su uno dei blog per vedere i post nella visualizzazione master/dettaglio.

Associazione di dati di esempio all'interfaccia utente nel modello Grid

Prima di eseguire questi passaggi, aggiorna il file di progetto data.js come descritto in Esempio di associazione dei dati all'interfaccia utente.

  1. Per usare il codice RSS di esempio nel modello Applicazione griglia, apri groupDetail.html.

    Questa pagina mostra un singolo gruppo (un blog) e gli elementi (post di blog) che fanno parte del gruppo.

  2. In groupDetail.html dobbiamo modificare alcune righe nell'elemento DIV con un nome di classe item-info. Modifica queste righe:

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

    in queste:

    <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 il modello di intestazione descrive informazioni di gruppo, non singoli elementi. Non dobbiamo quindi modificare la proprietà subtitle. Ecco il modello di intestazione:

    
    <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. Non disponiamo tuttavia di una proprietà description per ogni gruppo (ma solo per gli elementi) e quindi dobbiamo modificare la proprietà in updated nel codice precedente, come mostrato qui.

    <h4 class="group-description" data-win-bind="innerHTML: updated"></h4>
    
  4. Apri groupedItems.html, che mostra tutti i gruppi e i singoli post di blog che contengono.

  5. In questa pagina il modello di elemento generico WinJS visualizza singoli elementi (post di blog) e quindi dobbiamo aggiornare la proprietà subtitle. Modifica queste righe:

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

    in queste:

    <h6 class="item-subtitle win-type-ellipsis" 
        data-win-bind="textContent: author"></h6>
    
  6. Salva il progetto e premi F5 per eseguire il debug dell'app.

    Vedrai immediatamente il titolo della pagina, ma noterai un breve ritardo mentre vengono recuperati i dati del feed. Quando i dati vengono restituiti, come previsto, vedrai gli elementi in ogni blog nella home page. Fai clic su un'intestazione di gruppo per visualizzare la pagina del gruppo, oppure su un elemento per visualizzare un singolo post di blog.

Elenco del codice per data.js

Qui è riportato l'elenco del codice completo per data.js. Per entrambi gli esempi dei modelli Applicazione griglia e Applicazione divisa mostrati in precedenza, viene usato lo stesso file data.js. Per visualizzare il file data.js del modello Hub/Pivot, vedi Lettore Web JSON che usa il modello Hub/Pivot. Per visualizzare il file data.js del modello Hub, vedi Lettore Web JSON che usa il modello Hub.


(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
            });
        }
    }

})();

Argomenti correlati

Modelli di progetto JavaScript

Modelli di elemento JavaScript

Aggiunta di dati a un modello di progetto (C#, VB e C++)