Cet article a fait l’objet d’une traduction automatique. Pour afficher l’article en anglais, activez la case d’option Anglais. Vous pouvez également afficher le texte anglais dans une fenêtre contextuelle en faisant glisser le pointeur de la souris sur le texte traduit.
Traduction
Anglais
Informations
Le sujet que vous avez demandé est indiqué ci-dessous. Toutefois, ce sujet ne figure pas dans la bibliothèque.

Personnaliser l'expérience utilisateur à l'aide de SharePoint hébergée par le fournisseur des compléments

Personnaliser les composants d'expérience utilisateur SharePoint à distance à l'aide de hébergé par le fournisseur des compléments.

Dernière modification :mercredi 12 août 2015

S’applique à :Office 365 | SharePoint 2013 | SharePoint Online

Note Remarque

Le nom « Applications pour SharePoint » est remplacé par « Compléments SharePoint ». Lors de la période de transition, il se peut que la documentation et l’interface utilisateur de certains produits SharePoint et outils Visual Studio utilisent toujours le terme « applications pour SharePoint ». Pour plus d’informations, voir Nouveau nom des applications pour Office et SharePoint.

Cet article présente des exemples qui montrent les meilleures pratiques pour la personnalisation des composants UX SharePoint, y compris les scénarios suivants :

  • Manipulation de pages (ajout et modification d'une page wiki).

  • Affichage des compléments et des données dans les boîtes de dialogue modales.

  • Création d'éléments d'interface utilisateur personnalisés.

  • Rendu côté client (fichiers JSLink personnaliser le rendu des champs dans les listes SharePoint de déploiement).

  • Composant WebPart et la manipulation de composant du complément (provision à distance et exécuter un composant de script add-in dans un complément hébergé par le fournisseur).

  • Agrégation de données et la mise en cache (en utilisant le stockage local HTML5 et cookies HTTP pour réduire le nombre d'appels de service à SharePoint ).

L'exemple Core.ModifyPages inclut deux scénarios de manipulation de page :

  • Créer une page wiki.

  • Modifier la disposition d'une page wiki.

Cet exemple utilise la bibliothèque de pages de site par défaut et existant out-of-the-box mises en page. Vous pouvez également mettre à jour pour utiliser une bibliothèque de pages wiki personnalisé et de dispositions personnalisées. L'interface utilisateur de compléments inclut deux boutons qui créent des pages wiki et deux liens permettant d'afficher les pages wiki que vous créez.

La figure 1. Page de démarrage de l'exemple de manipulation de page

Page de lancement pour l’exemple de manipulation de page

L'exemple de code pour le premier scénario détermine si vous avez déjà créé la page wiki. Si ce n'est pas le cas, il ajoute le fichier à la bibliothèque de pages de site et retourne son URL.

Remarque Remarque

Le code dans cet article est fourni tel quel, sans garantie d’aucune sorte, expresse ou implicite, y compris mais sans s’y limiter, aucune garantie implicite d’adéquation à un usage particulier, à une qualité marchande ou une absence de contrefaçon.

var newpage = pageLibrary.RootFolder.Files.AddTemplateFile(newWikiPageUrl, TemplateFileType.WikiPage);
ctx.Load(newpage);
ctx.ExecuteQuery();
wikiPageUrl = String.Format("sitepages/{0}", wikiPageName);

Dans les deux scénarios, l'exemple ajoute le code HTML entré par le biais de la zone de texte sur la page de démarrage à l'aide de la méthode AddHtmlToWikiPage dans une classe d'assistance nommée LabHelper. Cette méthode insère le code HTML à partir du formulaire à l'intérieur du champ WikiField de la page wiki.

public void AddHtmlToWikiPage(ClientContext ctx, Web web, string folder, string html, string page)
        {
            Microsoft.SharePoint.Client.Folder pagesLib = web.GetFolderByServerRelativeUrl(folder);
            ctx.Load(pagesLib.Files);
            ctx.ExecuteQuery();

            Microsoft.SharePoint.Client.File wikiPage = null;

            foreach (Microsoft.SharePoint.Client.File aspxFile in pagesLib.Files)
            {
                if (aspxFile.Name.Equals(page, StringComparison.InvariantCultureIgnoreCase))
                {
                    wikiPage = aspxFile;
                    break;
                }
            }

            if (wikiPage == null)
            {
                return;
            }

            ctx.Load(wikiPage);
            ctx.Load(wikiPage.ListItemAllFields);
            ctx.ExecuteQuery();

            string wikiField = (string)wikiPage.ListItemAllFields["WikiField"];

            Microsoft.SharePoint.Client.ListItem listItem = wikiPage.ListItemAllFields;
            listItem["WikiField"] = html;
            listItem.Update();
            ctx.ExecuteQuery();
        }

L'exemple de code pour le deuxième scénario crée une nouvelle instance de WebPartEntity . Il utilise ensuite des méthodes dans une classe d'assistance pour remplir le composant WebPart XML. Le code XML affiche une liste de liens promus, y compris http://www.bing.com et la page d'accueil du référentiel Référentiels OfficeDev/PnP .

WebPartEntity wp2 = new WebPartEntity();
wp2.WebPartXml = new LabHelper().WpPromotedLinks(linksID, string.Format("{0}/Lists/{1}", 
                                                                Request.QueryString["SPHostUrl"], "Links"), 
                                                                string.Format("{0}/{1}", Request.QueryString["SPHostUrl"], 
                                                                scenario2PageUrl), "$Resources:core,linksList");
wp2.WebPartIndex = 1;
wp2.WebPartTitle = "Links";

new LabHelper().AddWebPartToWikiPage(ctx, ctx.Web, "SitePages", wp2, scenario2Page, 2, 1, false);
new LabHelper().AddHtmlToWikiPage(ctx, ctx.Web, "SitePages", htmlEntry.Text, scenario2Page, 2, 2);

this.hplPage2.NavigateUrl = string.Format("{0}/{1}", Request.QueryString["SPHostUrl"], scenario2PageUrl);

Le code d'assistance affiche les liens promus avec un tableau à l'intérieur d'un XsltListViewWebPart le composant WebPart.

La figure 2. Deuxième page wiki avec XsltListViewWebPart et d'une table de liens promus

Deuxième page wiki avec composant XsltListViewWeb et tableau de liens promus

L'objet WpPromotedLinks sur l'instance LabHelper contient du code XML qui définit l'apparence du composant WebPart qui sera possible d'injecter dans la page wiki. La méthode AddWebPartToWikiPage puis insérer le composant WebPart nouvellement défini à l'intérieur d'une nouvelle balise div dans la page wiki.

XmlDocument xd = new XmlDocument();
            xd.PreserveWhitespace = true;
            xd.LoadXml(wikiField);

            // Sometimes the wikifield content seems to be surrounded by an additional div. 
            XmlElement layoutsTable = xd.SelectSingleNode("div/div/table") as XmlElement;
            if (layoutsTable == null)
            {
                layoutsTable = xd.SelectSingleNode("div/table") as XmlElement;
            }

            XmlElement layoutsZoneInner = layoutsTable.SelectSingleNode(string.Format("tbody/tr[{0}]/td[{1}]/div/div", row, col)) as XmlElement;
            // - space element
            XmlElement space = xd.CreateElement("p");
            XmlText text = xd.CreateTextNode(" ");
            space.AppendChild(text);

            // - wpBoxDiv
            XmlElement wpBoxDiv = xd.CreateElement("div");
            layoutsZoneInner.AppendChild(wpBoxDiv);

            if (addSpace)
            {
                layoutsZoneInner.AppendChild(space);
            }

            XmlAttribute attribute = xd.CreateAttribute("class");
            wpBoxDiv.Attributes.Append(attribute);
            attribute.Value = "ms-rtestate-read ms-rte-wpbox";
            attribute = xd.CreateAttribute("contentEditable");
            wpBoxDiv.Attributes.Append(attribute);
            attribute.Value = "false";
            // - div1
            XmlElement div1 = xd.CreateElement("div");
            wpBoxDiv.AppendChild(div1);
            div1.IsEmpty = false;
            attribute = xd.CreateAttribute("class");
            div1.Attributes.Append(attribute);
            attribute.Value = "ms-rtestate-read " + wpdNew.Id.ToString("D");
            attribute = xd.CreateAttribute("id");
            div1.Attributes.Append(attribute);
            attribute.Value = "div_" + wpdNew.Id.ToString("D");
            // - div2
            XmlElement div2 = xd.CreateElement("div");
            wpBoxDiv.AppendChild(div2);
            div2.IsEmpty = false;
            attribute = xd.CreateAttribute("style");
            div2.Attributes.Append(attribute);
            attribute.Value = "display:none";
            attribute = xd.CreateAttribute("id");
            div2.Attributes.Append(attribute);
            attribute.Value = "vid_" + wpdNew.Id.ToString("D");

            ListItem listItem = webPartPage.ListItemAllFields;
            listItem["WikiField"] = xd.OuterXml;
            listItem.Update();
            ctx.ExecuteQuery();

L'exemple de Core.Dialog présente deux méthodes de l'incorporation des liens de boîte de dialogue modale. Ces liens affichent une page de complément hébergée dans un site hôte de SharePoint. Le complément utilise le modèle d'objet client (CSOM) pour créer l'action personnalisée et JavaScript pour démarrer et afficher des informations à l'intérieur de la boîte de dialogue. Car certaines de ces informations proviennent du site hôte, il utilise également le modèle d'objet JavaScript (JSOM) pour récupérer des informations à partir du site hôte. Et parce que le complément est en cours d'exécution dans un domaine différent du site hôte SharePoint, il utilise également la bibliothèque inter-domaines SharePoint pour réaliser les appels vers le site hôte.

Remarque Remarque

Pour plus d'informations sur l'utilisation de la bibliothèque inter-domaines dans ce scénario, voir Accéder à des données SharePoint 2013 à partir de compléments à l’aide de la bibliothèque inter-domaines.

La page de démarrage est la page qui s'affiche dans la boîte de dialogue. Pour gérer toutes les différences dans l'affichage, compte tenu du contexte d'affichage (boîte de dialogue par rapport à pleine page), le complément détermine si elle est affiché dans une boîte de dialogue. Pour cela, à l'aide d'un paramètre de chaîne de requête qui est transmis en même temps que les liens qui démarrent les boîtes de dialogue.

private string SetIsDlg(string isDlgValue)
        {
            var urlParams = HttpUtility.ParseQueryString(Request.QueryString.ToString());
            urlParams.Set("IsDlg", isDlgValue);
            return string.Format("{0}://{1}:{2}{3}?{4}", Request.Url.Scheme, Request.Url.Host, Request.Url.Port, Request.Url.AbsolutePath, urlParams.ToString());
        }

Vous pouvez, par exemple, choisir d'afficher certains éléments d'interface utilisateur (par exemple, les boutons) ou même différentes mises en page, selon le contenu en cours affiché dans une boîte de dialogue.

La page de démarrage de l'interface utilisateur présente deux options permettant de créer des liens vers la boîte de dialogue, ainsi qu'une liste de toutes les listes sur le site web hôte. Il présente également OK et Annuler les boutons que vous pouvez utiliser dans le contexte de boîte de dialogue pour fermer les boîte de dialogue zone et/ou invite actions supplémentaires dans le complément.

Lorsque vous cliquez sur le bouton de l'élément de menu Ajouter, le complément crée un objet CustomActionEntity qui démarre la boîte de dialogue. Il utilise ensuite la méthode d'extension OfficeDevPnP principale nommée AddCustomAction pour ajouter la nouvelle action personnalisée dans le menu Paramètres du Site.

StringBuilder modelDialogScript = new StringBuilder(10);
modelDialogScript.Append("javascript:var dlg=SP.UI.ModalDialog.showModalDialog({url: '");
modelDialogScript.Append(String.Format("{0}", SetIsDlg("1")));
modelDialogScript.Append("', dialogReturnValueCallback:function(res, val) {} });");       

// Create a custom action.
CustomActionEntity customAction = new CustomActionEntity()
{
  Title = "Office AMS Dialog sample",                
  Description = "Shows how to start an add-in inside a dialog box.",
  Location = "Microsoft.SharePoint.StandardMenu",
  Group = "SiteActions",
  Sequence = 10000,
  Url = modelDialogScript.ToString(),
};

// Add the custom action to the site.
cc.Web.AddCustomAction(customAction);

La méthode AddCustomAction ajoute l'action personnalisée à la collection de UserCustomActions qui est associée au site SharePoint.

var newAction = existingActions.Add();
            newAction.Description = customAction.Description;
            newAction.Location = customAction.Location;
            if (customAction.Location == JavaScriptExtensions.SCRIPT_LOCATION)
            {
                newAction.ScriptBlock = customAction.ScriptBlock;
            }
            else
            {
                newAction.Sequence = customAction.Sequence;
                newAction.Url = customAction.Url;
                newAction.Group = customAction.Group;
                newAction.Title = customAction.Title;
                newAction.ImageUrl = customAction.ImageUrl;
                if (customAction.Rights != null)
                {
                    newAction.Rights = customAction.Rights;
                }
            }
            newAction.Update();
            web.Context.Load(web, w => w.UserCustomActions);
            web.Context.ExecuteQuery();

Lorsque vous choisissez le bouton Ajouter une page avec composant WebPart Éditeur de script, le complément utilise les méthodes AddWikiPage et AddWebPartToWikiPage pour créer une page wiki à l'intérieur de la bibliothèque de pages de site et ajouter un composant WebPart Éditeur de Script configuré à la page.

string scenario1Page = String.Format("scenario1-{0}.aspx", DateTime.Now.Ticks);
string scenario1PageUrl = cc.Web.AddWikiPage("Site Pages", scenario1Page);
cc.Web.AddLayoutToWikiPage("SitePages", WikiPageLayout.OneColumn, scenario1Page);
WebPartEntity scriptEditorWp = new WebPartEntity();
scriptEditorWp.WebPartXml = ScriptEditorWebPart();
scriptEditorWp.WebPartIndex = 1;
scriptEditorWp.WebPartTitle = "Script editor test"; 
cc.Web.AddWebPartToWikiPage("SitePages", scriptEditorWp, scenario1Page, 1, 1, false);

La méthode AddWikiPage charge de la bibliothèque de pages du site. Si la page wiki spécifiée par le complément OfficeDevPnP principaux n'existe pas déjà, il crée la page.

public static string AddWikiPage(this Web web, string wikiPageLibraryName, string wikiPageName)
        {
            string wikiPageUrl = "";


            var pageLibrary = web.Lists.GetByTitle(wikiPageLibraryName);

            web.Context.Load(pageLibrary.RootFolder, f => f.ServerRelativeUrl);
            web.Context.ExecuteQuery();

            var pageLibraryUrl = pageLibrary.RootFolder.ServerRelativeUrl;
            var newWikiPageUrl = pageLibraryUrl + "/" + wikiPageName;

            var currentPageFile = web.GetFileByServerRelativeUrl(newWikiPageUrl);

            web.Context.Load(currentPageFile, f => f.Exists);
            web.Context.ExecuteQuery();

            if (!currentPageFile.Exists)
            {
                var newpage = pageLibrary.RootFolder.Files.AddTemplateFile(newWikiPageUrl, TemplateFileType.WikiPage);

                web.Context.Load(newpage);
                web.Context.ExecuteQuery();

                wikiPageUrl = UrlUtility.Combine("sitepages", wikiPageName);
            }

            return wikiPageUrl;
        }

La méthode AddWebPartToWikiPage insérer le composant WebPart nouvellement défini à l'intérieur d'une nouvelle balise <div> dans la page wiki. Il utilise ensuite le JSOM et la bibliothèque inter-domaines pour récupérer les informations qui figurent sur la liste des listes de SharePoint sur le site web hôte.

function printAllListNamesFromHostWeb() {
        var context;
        var factory;
        var appContextSite;
        var collList;

        context = new SP.ClientContext(appWebUrl);
        factory = new SP.ProxyWebRequestExecutorFactory(appWebUrl);
        context.set_webRequestExecutorFactory(factory);
        appContextSite = new SP.AppContextSite(context, spHostUrl);

        this.web = appContextSite.get_web();
        collList = this.web.get_lists();
        context.load(collList);

        context.executeQueryAsync(
            Function.createDelegate(this, successHandler),
            Function.createDelegate(this, errorHandler)
        );

Branding.UIElementPersonalization montre comment utiliser embedded JavaScript et les valeurs stockées dans les profils utilisateur et des listes de SharePoint pour personnaliser les éléments d'interface utilisateur sur le site web hôte. Il utilise également le stockage local HTML5 afin de réduire les appels vers le site hôte.

Page de démarrage de l'échantillon vous invite à ajouter une des trois chaînes (XX, AA ou ZZ) dans la section Informations personnelles de votre page de profil utilisateur.,

Le complément a déjà déployé trois images et une liste de SharePoint qui contient les titres et les URL pour chaque image, ainsi que d'un champ supplémentaire qui lie chaque image sur une des trois chaînes. Une fois que vous cliquez sur le bouton de Personnalisation de l'insertion, le complément incorpore le fichier personalize.js dans la collection d'actions personnalisées utilisateur.

public void AddPersonalizeJsLink(ClientContext ctx, Web web)
        {
            string scenarioUrl = String.Format("{0}://{1}:{2}/Scripts", this.Request.Url.Scheme,
                                                this.Request.Url.DnsSafeHost, this.Request.Url.Port);
            string revision = Guid.NewGuid().ToString().Replace("-", "");
            string personalizeJsLink = string.Format("{0}/{1}?rev={2}", scenarioUrl, "personalize.js", revision);

            StringBuilder scripts = new StringBuilder(@"
                var headID = document.getElementsByTagName('head')[0]; 
                var");

            scripts.AppendFormat(@"
                newScript = document.createElement('script');
                newScript.type = 'text/javascript';
                newScript.src = '{0}';
                headID.appendChild(newScript);", personalizeJsLink);
            string scriptBlock = scripts.ToString();

            var existingActions = web.UserCustomActions;
            ctx.Load(existingActions);
            ctx.ExecuteQuery();

            var actions = existingActions.ToArray();
            foreach (var action in actions)
            {
                if (action.Description == "personalize" &&
                    action.Location == "ScriptLink")
                {
                    action.DeleteObject();
                    ctx.ExecuteQuery();
                }
            }

            var newAction = existingActions.Add();
            newAction.Description = "personalize";
            newAction.Location = "ScriptLink";
            
            newAction.ScriptBlock = scriptBlock;
            newAction.Update();
            ctx.Load(web, s => s.UserCustomActions);
            ctx.ExecuteQuery();
        }

Étant donné que les sites d'équipe SharePoint par défaut utilisent la Stratégie de téléchargement Minimal (MDS), le code dans le fichier personalize.js tente d'abord de s'inscrire avec MDS. De cette manière, lors du chargement de la page qui contient le JavaScript, le MDS moteur starets la fonction principale (RemoteManager_Inject). Si le MDS est désactivée, cette fonction démarre immédiatement.

// Register script for MDS, if possible.
RegisterModuleInit("personalize.js", RemoteManager_Inject); //MDS registration
RemoteManager_Inject(); //non-MDS run

if (typeof (Sys) != "undefined" && Boolean(Sys) && Boolean(Sys.Application)) {
    Sys.Application.notifyScriptLoaded();h
}

if (typeof (NotifyScriptLoadedAndExecuteWaitingJobs) == "function") {
    NotifyScriptLoadedAndExecuteWaitingJobs("scenario1.js");
}
// The RemoteManager_Inject function is the entry point for loading the other scripts that perform the customizations. When a given script depends on another script, be sure to load the dependent script after the one on which it depends. This sample loads the JQuery library before the personalizeIt function that uses JQuery.
function RemoteManager_Inject() {

    var jQuery = "https://ajax.aspnetcdn.com/ajax/jQuery/jquery-2.0.2.min.js";

    // Load jQuery. 
    loadScript(jQuery, function () {

        personalizeIt();

    });
}

La fonction personalizeIt() vérifie le stockage local HTML5 il recherche des informations de profil utilisateur. Si elle accède aux informations de profil utilisateur, il stocke les informations qu'il récupère dans HTML5 du stockage local.

function personalizeIt() {
    clientContext = SP.ClientContext.get_current();

    var fileref = document.createElement('script');
    fileref.setAttribute("type", "text/javascript");
    fileref.setAttribute("src", "/_layouts/15/SP.UserProfiles.js");
    document.getElementsByTagName("head")[0].appendChild(fileref);

    SP.SOD.executeOrDelayUntilScriptLoaded(function () {        

        // Get localstorage values if they exist.
        buCode = localStorage.getItem("bucode");
        buCodeTimeStamp = localStorage.getItem("buCodeTimeStamp");

        // Determine whether the page already has embedded personalized image.
        var pageTitle = $('#pageTitle')[0].innerHTML;
        if (pageTitle.indexOf("img") > -1) {
            personalized = true;
        }
        else {
            personalized = false;
        }        

        // If nothing is in localstorage, get profile data, which will also populate localstorage.
        if (buCode == "" || buCode == null) {
            getProfileData(clientContext);
            personalized = false;
        }
        else {
            // Check for expiration.            
            if (isKeyExpired("buCodeTimeStamp")) {                
                getProfileData(clientContext);

                if (buCode != "" || buCode != null) {
                    // Set timestamp for expiration.
                    currentTime = Math.floor((new Date().getTime()) / 1000);
                    localStorage.setItem("buCodeTimeStamp", currentTime);

                    // Set personalized to false so that the code can check for a new image in case buCode was updated.
                    personalized = false;
                }
            }            
        }

        // Load image or make sure it is current based on the value in AboutMe.
        if (!personalized) {
            loadPersonalizedImage(buCode);
        }


    }, 'SP.UserProfiles.js');
}

Le fichier personalize.js contient également un code qui montre comment pour déterminer si la clé de stockage local a expiré. Cela n'est pas intégré dans le stockage local HTML5.

// Check to see if the key has expired
function isKeyExpired(TimeStampKey) {

    // Retrieve the example setting for expiration in seconds.
    var expiryStamp = localStorage.getItem(TimeStampKey);

    if (expiryStamp != null && cacheTimeout != null) {

        // Retrieve the timestamp and compare against specified cache timeout settings to see if it is expired.
        var currentTime = Math.floor((new Date().getTime()) / 1000);

        if (currentTime - parseInt(expiryStamp) > parseInt(cacheTimeout)) {
            return true; //Expired
        }
        else {
            return false;
        }
    }
    else {
        //default 
        return true;
    }
}

L'exemple Branding.ClientSideRendering montre comment utiliser un complément hébergé par le fournisseur de mise en service à distance SharePoint artefacts et des fichiers JSLink rendu côté client permettent de personnaliser l'apparence et le comportement des champs de liste SharePoint. Les fichiers JSLink et rendu côté client vous donnent tout contrôle sur le fonctionnement des contrôles sur une page SharePoint (affichages de liste, liste de champs et ajouter et modifier des formulaires) sont rendus. Ce contrôle peut réduire ou éliminer complètement le besoin pour les types de champ personnalisé. Rendu côté client rend possible contrôler à distance l'apparence du champ liste à distance.

L'exemple combine les exemples de JSLink dans les exemples de code côté Client rendu (JSLink) dans un seul hébergé par le fournisseur complément pour SharePoint qui met en service les fichiers JSLink. Rendu côté client vous permet d'utiliser des technologies web standard, tels que HTML et JavaScript, pour définir la logique de rendu des types de champ personnalisées et prédéfinies.

Lorsque vous démarrez l'exemple, la page de démarrage vous invite à mettre en service de tous les exemples.

La figure 3. Page de démarrage de l'échantillon de rendu côté client

Page de lancement de l’échantillon de rendu côté client

Lorsque vous choisissez d'Exemples de mise en service, le complément déploie une image ainsi que tous SharePoint listes, les affichages de liste, les éléments de liste, les formulaires et JavaScript les fichiers qui sont utilisés dans chaque exemple. Le complément crée un dossier nommé JSLink-exemples dans la bibliothèque de styles, puis télécharge les fichiers JavaScript dans ce dossier. La méthode UploadFileToFolder effectue le travail de téléchargement et de vérification dans chaque fichier JavaScript.

public static void UploadFileToFolder(Web web, string filePath, Folder folder)
        {
            using (FileStream fs = new FileStream(filePath, FileMode.Open))
            {
                FileCreationInformation flciNewFile = new FileCreationInformation();

                flciNewFile.ContentStream = fs;
                flciNewFile.Url = System.IO.Path.GetFileName(filePath);
                flciNewFile.Overwrite = true;

                Microsoft.SharePoint.Client.File uploadFile = folder.Files.Add(flciNewFile);
                uploadFile.CheckIn("CSR sample js file", CheckinType.MajorCheckIn);

                folder.Context.Load(uploadFile);
                folder.Context.ExecuteQuery();
            }
        }

Exemple 1: Appliquer la mise en forme à une colonne de liste

L'exemple 1 montre comment appliquer la mise en forme à une colonne de liste en fonction de la valeur du champ. Valeurs de champ de priorité 1 (haute), 2 (Normal) et 3 (faible) sont affichés en rouge, orange et de jaune.

La figure 4. Affichage du champ de liste personnalisée

Affichage des champs de liste personnalisée

Le suivant JavaScript remplace l'affichage du champ par défaut et crée un nouveau modèle d'affichage pour le champ de la liste priorité. La technique dans la fonction anonyme qui charge des informations contextuelles sur le champ dont vous souhaitez remplacer l'affichage est utilisée dans tous les exemples.

(function () {

    // Create object that has the context information about the field that you want to render differently.
    var priorityFiledContext = {};
    priorityFiledContext.Templates = {};
    priorityFiledContext.Templates.Fields = {
        // Apply the new rendering for Priority field in List View.
        "Priority": { "View": priorityFiledTemplate }
    };

    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(priorityFiledContext);

})();

// This function provides the rendering logic for list view.
function priorityFiledTemplate(ctx) {

    var priority = ctx.CurrentItem[ctx.CurrentFieldSchema.Name];

    // Return HTML element with appropriate color based on the Priority column’s value.
    switch (priority) {
        case "(1) High":
            return "<span style='color :#f00'>" + priority + "</span>";
            break;
        case "(2) Normal":
            return "<span style='color :#ff6a00'>" + priority + "</span>";
            break;
        case "(3) Low":
            return "<span style='color :#cab023'>" + priority + "</span>";
    }
}

Exemple 2: Raccourcir le texte long

Exemple 2 montre comment tronquer texte long stockée dans le champ Body d'une liste d'annonces. Le texte intégral s'affiche sous la forme d'un menu contextuel qui s'affiche chaque fois que vous placez sur un élément de liste, comme illustré dans la Figure 8.

La figure 5. Menu contextuel de liste raccourcie champ Affichage montrant

Affichage des champs de liste tronqués avec le menu contextuel

Le suivant JavaScript réduit le texte du champ Body et entraîne le texte intégral apparaissent sous la forme d'un menu contextuel par le biais de l'attribut title sur la balise span .

function bodyFiledTemplate(ctx) {

    var bodyValue = ctx.CurrentItem[ctx.CurrentFieldSchema.Name];

    // This regex expression is used to delete HTML tags from the Body field.
    var regex = /(<([^>]+)>)/ig;

    bodyValue = bodyValue.replace(regex, "");

    var newBodyValue = bodyValue;

    if (bodyValue && bodyValue.length >= 100)
    {
        newBodyValue = bodyValue.substring(0, 100) + " ...";
    }

    return "<span title='" + bodyValue + "'>" + newBodyValue + "</span>";

}

Exemple 3: Afficher une image avec un nom de document

Exemple 3 montre comment afficher une image en regard du nom d'un document à l'intérieur d'une bibliothèque de documents. Une étiquette rouge s'affiche chaque fois que la valeur de champ Confidential est définie sur Yes, comme le montre la Figure 6.

La figure 6. Affichage de l'image en regard du nom du document

Image affichée en regard du nom du document

Le suivant JavaScript vérifie la valeur du champ Confidential , puis personnalise l'affichage du champ Name en fonction de la valeur d'un autre champ. L'exemple utilise l'image qui est téléchargé lorsque vous cliquez sur Exemples de mise en service.

function linkFilenameFiledTemplate(ctx) {

    var confidential = ctx.CurrentItem["Confidential"];
    var title = ctx.CurrentItem["FileLeafRef"];

    // This Regex expression use to delete extension (.docx, .pdf ...) form the file name.
    title = title.replace(/\.[^/.]+$/, "")

    // Check confidential field value.
    if (confidential && confidential.toLowerCase() == 'yes') {
        // Render HTML that contains the file name and the confidential icon
        return title + "&nbsp;<img src= '" + _spPageContextInfo.siteServerRelativeUrl + "/Style%20Library/JSLink-Samples/imgs/Confidential.png' alt='Confidential Document' title='Confidential Document'/>";
    }
    else
    {
        return title;
    }
}

Exemple 4: Afficher un graphique à barres

L'exemple 4 montre comment afficher un graphique à barres dans le champ % achevé d'une liste de tâches. L'apparence du graphique à barres dépend de la valeur du champ % achevé, comme le montre la Figure 10. Notez qu'un graphique en barres figurent également dans les formulaires pour créer et modifier des éléments de liste de tâches.

Le code suivant crée l'affichage graphique à barres et associe avec les formulaires de l'affichage et l'affichage (percentCompleteViewFiledTemplate), puis avec le nouveau et modifier des formulaires (percentCompleteEditFiledTemplate).

// This function provides the rendering logic for View and Display forms.
function percentCompleteViewFiledTemplate(ctx) {

    var percentComplete = ctx.CurrentItem[ctx.CurrentFieldSchema.Name];
    return "<div style='background-color: #e5e5e5; width: 100px;  display:inline-block;'> \
            <div style='width: " + percentComplete.replace(/\s+/g, '') + "; background-color: #0094ff;'> \
            &nbsp;</div></div>&nbsp;" + percentComplete;

}

// This function provides the rendering logic for New and Edit forms.
function percentCompleteEditFiledTemplate(ctx) {

    var formCtx = SPClientTemplates.Utility.GetFormContextForCurrentField(ctx);

    // Register a callback just before submit.
    formCtx.registerGetValueCallback(formCtx.fieldName, function () {
        return document.getElementById('inpPercentComplete').value;
    });

    return "<input type='range' id='inpPercentComplete' name='inpPercentComplete' min='0' max='100' \
            oninput='outPercentComplete.value=inpPercentComplete.value' value='" + formCtx.fieldValue + "' /> \
            <output name='outPercentComplete' for='inpPercentComplete' >" + formCtx.fieldValue + "</output>%";
}

La figure 7. Graphique à barres affichée dans le champ % achevé

Diagramme à barres affiché dans le champ « % effectué »

Exemple 5: Modifier le modèle de rendu

Exemple 5 montre comment modifier le modèle de rendu d'un affichage de liste. Cette vue affiche les titres d'élément de liste qui étendent comme accordéons lorsque vous sélectionnez les. L'affichage étendu vous présente les champs d'élément de liste supplémentaires, comme le montre la Figure 8.

La figure 8. Vues des éléments de liste développée et réduite

Vues des éléments dans les listes développées et réduites

Le code suivant définit le modèle et l'enregistre avec le modèle de liste. Il définit la mise en page globale et utilise ensuite le Gestionnaire d'événements OnPostRender pour inscrire la fonction JavaScript qui s'exécute lors du rendu de la liste. Cette fonction associe l'événement à la CSS et que la gestion des événements implémente la fonctionnalité accordéon.

(function () {

    // jQuery library is required in this sample.
    // Fallback to loading jQuery from a CDN path if the local is unavailable
    (window.jQuery || document.write('<script src="//ajax.aspnetcdn.com/ajax/jquery/jquery-1.10.0.min.js"><\/script>'));

    // Create object that has the context information about the field that you want to render differently.
    var accordionContext = {};
    accordionContext.Templates = {};

    // Be careful when adding the header for the template, because it will break the default list view render.
    accordionContext.Templates.Header = "<div class='accordion'>";
    accordionContext.Templates.Footer = "</div>";

    // Add OnPostRender event handler to add accordion click events and style.
    accordionContext.OnPostRender = accordionOnPostRender;

    // This line of code tells the TemplateManager that you want to change all the HTML for item row rendering.
    accordionContext.Templates.Item = accordionTemplate;

    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(accordionContext);

})();

// This function provides the rendering logic.
function accordionTemplate(ctx) {
    var title = ctx.CurrentItem["Title"];
    var description = ctx.CurrentItem["Description"];

    // Return whole item html
    return "<h2>" + title + "</h2><p>" + description + "</p><br/>";
}

function accordionOnPostRender() {

    // Register event to collapse and expand when selecting accordion header.
    $('.accordion h2').click(function () {
        $(this).next().slideToggle();
    }).next().hide();

    $('.accordion h2').css('cursor', 'pointer');
}

Exemple 6: Valider les valeurs de champ

Exemple 6 vous indique comment utiliser des expressions régulières pour valider les valeurs des champs fournis par l'utilisateur. Un message d'erreur rouge s'affiche lorsque l'utilisateur tape une adresse de messagerie non valide dans la zone de texte du champ courrier électronique. Cela se produit lorsque l'utilisateur crée ou modifie un élément de liste, comme illustré à la Figure 9.

La figure 9. Message d'erreur d'entrée de texte de champ non valide

Message d’erreur affiché en cas de saisie d’un texte non valide dans un champ

Le code suivant définit le modèle avec un espace réservé pour l'affichage du message d'erreur et enregistre les fonctions de rappel qui se déclenchent chaque fois que l'utilisateur tente d'envoyer les formulaires. Le premier rappel renvoie la valeur de la colonne adresse de messagerie et le deuxième rappel utilise des expressions régulières pour valider la valeur de chaîne.

function emailFiledTemplate(ctx) {

    var formCtx = SPClientTemplates.Utility.GetFormContextForCurrentField(ctx);

    // Register a callback just before submit.
    formCtx.registerGetValueCallback(formCtx.fieldName, function () {
        return document.getElementById('inpEmail').value;
    });

    // Create container for various validations.
    var validators = new SPClientForms.ClientValidation.ValidatorSet();
    validators.RegisterValidator(new emailValidator());

    // Validation failure handler.
    formCtx.registerValidationErrorCallback(formCtx.fieldName, emailOnError);

    formCtx.registerClientValidator(formCtx.fieldName, validators);

    return "<span dir='none'><input type='text' value='" + formCtx.fieldValue + "'  maxlength='255' id='inpEmail' class='ms-long'> \
            <br><span id='spnError' class='ms-formvalidation ms-csrformvalidation'></span></span>";
}

// Custom validation object to validate email format.
emailValidator = function () {
    emailValidator.prototype.Validate = function (value) {
        var isError = false;
        var errorMessage = "";

        //Email format Regex expression
        var emailRejex = /\S+@\S+\.\S+/;

        if (!emailRejex.test(value) && value.trim()) {
            isError = true;
            errorMessage = "Invalid email address";
        }

        // Send error message to error callback function (emailOnError).
        return new SPClientForms.ClientValidation.ValidationResult(isError, errorMessage);
    };
};

// Add error message to spnError element under the input field element.
function emailOnError(error) {
    document.getElementById("spnError").innerHTML = "<span role='alert'>" + error.errorMessage + "</span>";
}

Exemple 7: Rendre les éléments de liste modifier des champs en lecture seule

Exemple sept montre comment rendre la liste des champs de formulaire de modification élément en lecture seule. Les champs en lecture seule affichent sans contrôles d'édition, comme le montre la Figure 10.

La figure 10. Formulaire de modification de champ en lecture seule dans une liste personnalisée

Champs en lecture seule dans un formulaire de modification de liste personnalisée

L'exemple de code suivant modifie le titre, AssignedTo, et le formulaire de modification des champs de priorité dans l'élément de liste afin qu'ils indiquent les valeurs de champ uniquement avec aucun des contrôles d'édition. Le code montre comment gérer les exigences de l'analyse de différents types de champ.

function readonlyFieldTemplate(ctx) {

    // Reuse SharePoint JavaScript libraries.
    switch (ctx.CurrentFieldSchema.FieldType) {
        case "Text":
        case "Number":
        case "Integer":
        case "Currency":
        case "Choice":
        case "Computed":
            return SPField_FormDisplay_Default(ctx);

        case "MultiChoice":
            prepareMultiChoiceFieldValue(ctx);
            return SPField_FormDisplay_Default(ctx);

        case "Boolean":
            return SPField_FormDisplay_DefaultNoEncode(ctx);

        case "Note":
            prepareNoteFieldValue(ctx);
            return SPFieldNote_Display(ctx);

        case "File":
            return SPFieldFile_Display(ctx);

        case "Lookup":
        case "LookupMulti":
                return SPFieldLookup_Display(ctx);           

        case "URL":
            return RenderFieldValueDefault(ctx);

        case "User":
            prepareUserFieldValue(ctx);
            return SPFieldUser_Display(ctx);

        case "UserMulti":
            prepareUserFieldValue(ctx);
            return SPFieldUserMulti_Display(ctx);

        case "DateTime":
            return SPFieldDateTime_Display(ctx);

        case "Attachments":
            return SPFieldAttachments_Default(ctx);

        case "TaxonomyFieldType":
            //Re-use JavaScript from the sp.ui.taxonomy.js SharePoint JavaScript library
            return SP.UI.Taxonomy.TaxonomyFieldTemplate.renderDisplayControl(ctx);
    }
}

// User control needs specific formatted value to render content correctly.
function prepareUserFieldValue(ctx) {
    var item = ctx['CurrentItem'];
    var userField = item[ctx.CurrentFieldSchema.Name];
    var fieldValue = "";

    for (var i = 0; i < userField.length; i++) {
        fieldValue += userField[i].EntityData.SPUserID + SPClientTemplates.Utility.UserLookupDelimitString + userField[i].DisplayText;

        if ((i + 1) != userField.length) {
            fieldValue += SPClientTemplates.Utility.UserLookupDelimitString
        }
    }

    ctx["CurrentFieldValue"] = fieldValue;
}

// Choice control needs specific formatted value to render content correctly.
function prepareMultiChoiceFieldValue(ctx) {

    if (ctx["CurrentFieldValue"]) {
        var fieldValue = ctx["CurrentFieldValue"];

        var find = ';#';
        var regExpObj = new RegExp(find, 'g');

        fieldValue = fieldValue.replace(regExpObj, '; ');
        fieldValue = fieldValue.replace(/^; /g, '');
        fieldValue = fieldValue.replace(/; $/g, '');

        ctx["CurrentFieldValue"] = fieldValue;
    }
}

// Note control needs specific formatted value to render content correctly.
function prepareNoteFieldValue(ctx) {

    if (ctx["CurrentFieldValue"]) {
        var fieldValue = ctx["CurrentFieldValue"];
        fieldValue = "<div>" + fieldValue.replace(/\n/g, '<br />'); + "</div>";

        ctx["CurrentFieldValue"] = fieldValue;
    }
} 

Exemple 8: Masquer des champs

Exemple 8 montre comment masquer les champs dans l'élément de liste nouveau et modifier des formulaires. L'exemple masque le champ prédécesseurs lorsqu'un utilisateur crée ou modifie un élément de liste de tâches.

Cet exemple déploie que le modifier et le nouveau formulaire pour une liste appelée liste de contrôles de masquer CSR. Pour plus d'informations sur la façon d'afficher le formulaire après le déploiement de l'exemple, voir Branding.ClientSideRendering.

Le code suivant recherche le champ prédécesseurs dans le code HTML du formulaire et masque. Le champ reste présent dans le code HTML, mais l'utilisateur ne peut pas l'afficher dans le navigateur.

(function () {

    // jQuery library is required in this sample.
    // Fallback to loading jQuery from a CDN path if the local is unavailable.
    (window.jQuery || document.write('<script src="//ajax.aspnetcdn.com/ajax/jquery/jquery-1.10.0.min.js"><\/script>'));

    // Create object that has the context information about the field that we want to render differently.
    var hiddenFiledContext = {};
    hiddenFiledContext.Templates = {}; 
    hiddenFiledContext.Templates.OnPostRender = hiddenFiledOnPreRender;
    hiddenFiledContext.Templates.Fields = {
        // Apply the new rendering for Predecessors field in New and Edit forms.
        "Predecessors": {
            "NewForm": hiddenFiledTemplate,
            "EditForm": hiddenFiledTemplate
        }
    };

    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(hiddenFiledContext);

})();


// This function provides the rendering logic.
function hiddenFiledTemplate() {
    return "<span class='csrHiddenField'></span>";
}

// This function provides the rendering logic.
function hiddenFiledOnPreRender(ctx) {
    jQuery(".csrHiddenField").closest("tr").hide();
}

L'exemple Core.AppScriptPart illustre l'utilisation des composants de script complément à incorporer des scripts qui s'exécutent dans un complément hébergé par le fournisseur sur une page SharePoint. Cet exemple montre comment modifier l'interface utilisateur d'une page sur le site hôte en déployant un composant de script du complément et en ajoutant à une page SharePoint à partir de la galerie de composants webpart.

Un composant de script du complément ressemble à un composant WebPart dans la mesure où vous pouvez l'ajouter à une page SharePoint à partir de la galerie de composants WebPart, mais dans ce cas le fichier .webpart incorpore un fichier JavaScript qui s'exécute à distance dans un complément hébergé par le fournisseur. Le composant de script add-in s'exécute à l'intérieur d'une balise <div> dans la page SharePoint et par conséquent fournit une conception plus vite et l'expérience que vous obtiennent avec les composants de compléments qui s'exécutent dans un IFRAME.

La page de démarrage inclut un bouton Exécuter un scénario qui déploie le composant de script de macro complémentaire à la galerie de composants WebPart. L'exemple de code suivant construit une instance de FileCreationInformationObject qui renferme le contenu du fichier .webpart et puis télécharge le nouveau fichier dans la galerie de composants WebPart. Notez que vous pouvez également exécuter ce code automatiquement lorsque le complément à installer ou dans le cadre du processus de mise en service la collection de sites.

var spContext = SharePointContextProvider.Current.GetSharePointContext(Context);
using (var clientContext = spContext.CreateUserClientContextForSPHost())
{
    var folder = clientContext.Web.Lists.GetByTitle("Web Part Gallery").RootFolder;
    clientContext.Load(folder);
    clientContext.ExecuteQuery();

    // Upload the OneDrive for Business Usage Guidelines.docx.
    using (var stream = System.IO.File.OpenRead(Server.MapPath("~/userprofileinformation.webpart")))
    {
        FileCreationInformation fileInfo = new FileCreationInformation();
        fileInfo.ContentStream = stream;
        fileInfo.Overwrite = true;
        fileInfo.Url = "userprofileinformation.webpart";
        File file = folder.Files.Add(fileInfo);
        clientContext.ExecuteQuery();
    }

    // Update the group for uplaoded web part.
    var list = clientContext.Web.Lists.GetByTitle("Web Part Gallery");
    CamlQuery camlQuery = CamlQuery.CreateAllItemsQuery(100);
    Microsoft.SharePoint.Client.ListItemCollection items = list.GetItems(camlQuery);
    clientContext.Load(items);
    clientContext.ExecuteQuery();
    foreach (var item in items)
    {
        // Random group name to differentiate it from the rest.
        if (item["FileLeafRef"].ToString().ToLowerInvariant() == "userprofileinformation.webpart")
        {
            item["Group"] = "add-in Script Part";
            item.Update();
            clientContext.ExecuteQuery();
        }
    }

    lblStatus.Text = string.Format("add-in script part has been added to web part gallery. You can find 'User Profile Information' script part under 'Add-in Script Part' group in the <a href='{0}'>host web</a>.", spContext.SPHostUrl.ToString());
}

Une fois que vous avez terminé cette étape, vous pouvez trouver le composant de script complément les informations de profil utilisateur à l'intérieur d'une nouvelle catégorie D'ajouter le composant de Script dans la galerie de composants WebPart. Après avoir ajouté le composant de script de macro complémentaire à la page, la distance en cours d'exécution JavaScript contrôle l'affichage des informations sur la page.

Lorsque vous affichez le composant de script add-in en mode édition, vous verrez qu'il incorpore le fichier JavaScript qui est en cours d'exécution à distance. Le script userprofileinformation.js utilise le JSOM pour obtenir des informations de profil utilisateur à partir du site hôte.

function sharePointReady() {
  clientContext = SP.ClientContext.get_current();

  var fileref = document.createElement('script');
  fileref.setAttribute("type", "text/javascript");
  fileref.setAttribute("src", "/_layouts/15/SP.UserProfiles.js");
  document.getElementsByTagName("head")[0].appendChild(fileref);

  SP.SOD.executeOrDelayUntilScriptLoaded(function () {

    //Get Instance of People Manager Class       
    var peopleManager = new SP.UserProfiles.PeopleManager(clientContext);

    //Get properties of the current user
    userProfileProperties = peopleManager.getMyProperties();
    clientContext.load(userProfileProperties);
    clientContext.executeQueryAsync(Function.createDelegate(this, function (sender, args) {
      var firstname = userProfileProperties.get_userProfileProperties()['FirstName'];
      var name = userProfileProperties.get_userProfileProperties()['PreferredName'];
      var title = userProfileProperties.get_userProfileProperties()['Title'];
      var aboutMe = userProfileProperties.get_userProfileProperties()['AboutMe'];
      var picture = userProfileProperties.get_userProfileProperties()['PictureURL'];

      var html = "<div><h2>Welcome " + firstname + "</h2></div><div><div style='float: left; margin-left:10px'><img style='float:left;margin-right:10px' src='" + picture + "' /><b>Name</b>: " + name + "<br /><b>Title</b>: " + title + "<br />" + aboutMe + "</div></div>";

      document.getElementById('UserProfileAboutMe').innerHTML = html;
    }), Function.createDelegate(this, function (sender, args) {
      console.log('The following error has occurred while loading user profile property: ' + args.get_message());
    }));
  }, 'SP.UserProfiles.js');
}

L'exemple Provisioning.PublishingFeatures montre comment effectuer des tâches courantes avec publication de sites qui sont hébergés sur Office 365; par exemple, mise en service et à l'aide de mises en page, les pages maîtres et les thèmes ou incorporation JavaScript mises en page. Il indique également comment appliquer des filtres qui déterminent quels modèles de site sont disponibles pour les sous-sites et les mises en page sont disponibles sur le site web hôte.

Le complément hébergé par le fournisseur utilise CSOM pour couramment utilisée pour mettre en service les éléments d'interface utilisateur sur les sites de publication et qu'il utilise JavaScript pour créer des expériences plus dynamiques dans les mises en page que vous pouvez déployer pour les sites de publication. Il indique également les différences entre l'utilisation des pages maîtres et les thèmes dans les sites de publication.

Remarque importante Importante

Pour rendre la fonctionnalité de travail de cet exemple, vous devez activer les fonctionnalités de publication sur votre site. Pour plus d'informations, consultez la rubrique Activer les fonctionnalités de publication.

L'exemple de page de démarrage vous propose trois scénarios de personnalisation de l'interface utilisateur des sites de publication :

  • Déployer des mises en page.

  • Déployer des thèmes et des pages maîtres.

  • Filtrer les mises en page disponibles et les modèles de site sur le site hôte.

Scénario 1: Déployer des pages

Scénario 1 vous montre comment déployer une mise en page personnalisée. Le bouton de mises en page de déployer indiqué dans la Figure 11 crée une nouvelle mise en page et une page qui utilise cette mise en page.

La figure 11. Bouton pour déployer des mises en page

Bouton qui déploie les mises en page

Vous pouvez afficher la nouvelle page en accédant à la page de démonstration nouvellement créé sur votre site de l'hôte, qui contient incorporé JavaScript et affiche les informations de profil utilisateur.

L'exemple affiche les informations de cet utilisateur sur la page. Il alsoadds une page, bien que dans ce cas, il utilise un objet PublishingPageInformation pour créer la nouvelle page.

L'exemple ajoute une nouvelle mise en page en téléchargeant un fichier à la galerie de pages maîtres et en affectant le type de contenu de mise en page. Le code suivant prend le chemin d'accès à un fichier *.aspx (que vous pouvez déployer en tant que ressource dans votre projet Visual Studio 2013 ) et l'ajoute en tant qu'une mise en page dans la galerie de pages maîtres.

// Get the path to the file that you are about to deploy.
            List masterPageGallery = web.GetCatalog((int)ListTemplateType.MasterPageCatalog);
            Folder rootFolder = masterPageGallery.RootFolder;
            web.Context.Load(masterPageGallery);
            web.Context.Load(rootFolder);
            web.Context.ExecuteQuery();

            var fileBytes = System.IO.File.ReadAllBytes(sourceFilePath);

            // Use CSOM to upload the file.
            FileCreationInformation newFile = new FileCreationInformation();
            newFile.Content = fileBytes;
            newFile.Url = UrlUtility.Combine(rootFolder.ServerRelativeUrl, fileName);
            newFile.Overwrite = true;

            Microsoft.SharePoint.Client.File uploadFile = rootFolder.Files.Add(newFile);
            web.Context.Load(uploadFile);
            web.Context.ExecuteQuery();

            // Check out the file if needed.
            if (masterPageGallery.ForceCheckout || masterPageGallery.EnableVersioning)
            {
                if (uploadFile.CheckOutType == CheckOutType.None)
                {
                    uploadFile.CheckOut();
                }
            }

            // Get content type for ID to assign associated content type information.
            ContentType associatedCt = web.GetContentTypeById(associatedContentTypeID);

            var listItem = uploadFile.ListItemAllFields;
            listItem["Title"] = title;
            listItem["MasterPageDescription"] = description;
            // Set the item as page layout.
            listItem["ContentTypeId"] = Constants.PAGE_LAYOUT_CONTENT_TYPE;
            // Set the associated content type ID property
            listItem["PublishingAssociatedContentType"] = string.Format(";#{0};#{1};#", associatedCt.Name, associatedCt.Id);
            listItem["UIVersion"] = Convert.ToString(15);
            listItem.Update();

            // Check in the page layout if needed.
            if (masterPageGallery.ForceCheckout || masterPageGallery.EnableVersioning)
            {
                uploadFile.CheckIn(string.Empty, CheckinType.MajorCheckIn);
                listItem.File.Publish(string.Empty);
            }
            web.Context.ExecuteQuery();

Vous pouvez vérifier que votre nouvelle page est à l'aide de la nouvelle mise en page en accédant à la bibliothèque de Pages du site hôte.

Scénario 2: Déployer des thèmes et des pages maîtres

Scénario 2 vous montre comment déployer et de définir des pages maîtres et des thèmes pour le site de l'hôte à partir d'un complément hébergé par le fournisseur. Lorsque vous choisissez Deploy master et l'utiliser dans l'exemple de page de démarrage, l'exemple déploie et applique une page maître personnalisée pour le site hôte. Vous pouvez voir la nouvelle page maître en accédant à la page d'accueil du site.

L'exemple ajoute une nouvelle page maître en téléchargeant un fichier *.master à la galerie de pages maîtres et en affectant le type de contenu de page maître. Le code suivant prend le chemin d'accès à un fichier *.master (que vous pouvez déployer en tant que ressource dans votre projet Visual Studio 2013 ) et l'ajoute en tant que page maître dans la galerie de pages maîtres.

string fileName = Path.GetFileName(sourceFilePath);

            // Get the path to the file that you are about to deploy.
            List masterPageGallery = web.GetCatalog((int)ListTemplateType.MasterPageCatalog);
            Folder rootFolder = masterPageGallery.RootFolder;
            web.Context.Load(masterPageGallery);
            web.Context.Load(rootFolder);
            web.Context.ExecuteQuery();

            // Get the file name from the provided path.
            var fileBytes = System.IO.File.ReadAllBytes(sourceFilePath);

            // Use CSOM to upload the file.
            FileCreationInformation newFile = new FileCreationInformation();
            newFile.Content = fileBytes;
            newFile.Url = UrlUtility.Combine(rootFolder.ServerRelativeUrl, fileName);
            newFile.Overwrite = true;

            Microsoft.SharePoint.Client.File uploadFile = rootFolder.Files.Add(newFile);
            web.Context.Load(uploadFile);
            web.Context.ExecuteQuery();


            var listItem = uploadFile.ListItemAllFields;
            if (masterPageGallery.ForceCheckout || masterPageGallery.EnableVersioning)
            {
                if (uploadFile.CheckOutType == CheckOutType.None)
                {
                    uploadFile.CheckOut();
                }
            }

            listItem["Title"] = title;
            listItem["MasterPageDescription"] = description;
            // Set content type as master page.
            listItem["ContentTypeId"] = Constants.MASTERPAGE_CONTENT_TYPE;
            listItem["UIVersion"] = uiVersion;
            listItem.Update();
            if (masterPageGallery.ForceCheckout || masterPageGallery.EnableVersioning)
            {
                uploadFile.CheckIn(string.Empty, CheckinType.MajorCheckIn);
                listItem.File.Publish(string.Empty);
            }
            web.Context.Load(listItem);
            web.Context.ExecuteQuery();

L'étape suivante consiste à définir l'URL de la nouvelle page maître comme valeur de la MasterUrl et CustomMasterUrl des propriétés de l'objet Web qui représente le site. L'exemple gère cette avec une seule méthode qui extrait l'URL de la nouvelle page maître dans la galerie de pages maîtres et affecte cette valeur pour les propriétés Web.MasterUrl et Web.CustomMasterUrl .

// Assign master page to the host web.
                clientContext.Web.SetMasterPagesForSiteByName("contoso.master", "contoso.master");

Lorsque vous choisissez de déployer le thème et l'utiliser, l'exemple déploie et applique un thème personnalisé sur le site hôte. L'exemple définit la palette de couleurs, une image d'arrière-plan et un jeu de polices du thème en ajoutant un nouveau thème avec ces valeurs (que vous pouvez déployer en tant que ressources au sein de votre projet Visual Studio 2013 ) à la galerie de thèmes. Le code suivant crée le nouveau thème.

List themesOverviewList = web.GetCatalog((int)ListTemplateType.DesignCatalog);
           web.Context.Load(themesOverviewList);
           web.Context.ExecuteQuery(); 
                ListItemCreationInformation itemInfo = new ListItemCreationInformation();
                Microsoft.SharePoint.Client.ListItem item = themesOverviewList.AddItem(itemInfo);
                item["Name"] = themeName;
                item["Title"] = themeName;
                if (!string.IsNullOrEmpty(colorFileName))
                {
                    item["ThemeUrl"] = UrlUtility.Combine(rootWeb.ServerRelativeUrl, string.Format(Constants.THEMES_DIRECTORY, Path.GetFileName(colorFileName)));
                }
                if (!string.IsNullOrEmpty(fontFileName))
                {
                    item["FontSchemeUrl"] = UrlUtility.Combine(rootWeb.ServerRelativeUrl, string.Format(Constants.THEMES_DIRECTORY, Path.GetFileName(fontFileName)));
                }
                if (!string.IsNullOrEmpty(backgroundName))
                {
                    item["ImageUrl"] = UrlUtility.Combine(rootWeb.ServerRelativeUrl, string.Format(Constants.THEMES_DIRECTORY, Path.GetFileName(backgroundName)));
                }
                item["DisplayOrder"] = 11;
                item.Update();
                web.Context.ExecuteQuery();

               

L'étape suivante consiste à définir ce nouveau thème comme le thème du site. Le code suivant effectue cette action par l'extraction du thème à partir de la galerie de thèmes et d'appliquer ses valeurs sur le site hôte.

 CamlQuery query = new CamlQuery();
                // Find the theme by themeName.
                string camlString = string.Format(CAML_QUERY_FIND_BY_FILENAME, themeName);
                query.ViewXml = camlString;
                var found = themeList.GetItems(query);
                rootWeb.Context.Load(found);
                LoggingUtility.Internal.TraceVerbose("Getting theme: {0}", themeName);
                rootWeb.Context.ExecuteQuery();
                if (found.Count > 0)
                {
                    ListItem themeEntry = found[0];

                    / /Set the properties for applying the custom theme that was just uploaded.
                    string spColorURL = null;
                    if (themeEntry["ThemeUrl"] != null && themeEntry["ThemeUrl"].ToString().Length > 0)
                    {
                        spColorURL = UrlUtility.MakeRelativeUrl((themeEntry["ThemeUrl"] as FieldUrlValue).Url);
                    }
                    string spFontURL = null;
                    if (themeEntry["FontSchemeUrl"] != null && themeEntry["FontSchemeUrl"].ToString().Length > 0)
                    {
                        spFontURL = UrlUtility.MakeRelativeUrl((themeEntry["FontSchemeUrl"] as FieldUrlValue).Url);
                    }
                    string backGroundImage = null;
                    if (themeEntry["ImageUrl"] != null && themeEntry["ImageUrl"].ToString().Length > 0)
                    {
                        backGroundImage = UrlUtility.MakeRelativeUrl((themeEntry["ImageUrl"] as FieldUrlValue).Url);
                    }

                    // Set theme for demonstration.
                    // TODO: Why is shareGenerated false? If deploying to root an inheriting, then maybe use shareGenerated = true.
                    web.ApplyTheme(spColorURL,
                                        spFontURL,
                                        backGroundImage,
                                        false);
                    web.Context.ExecuteQuery();

Scénario 3: Filtrer les mises en page disponibles et les modèles de sites

Scénario 3 vous indique comment limiter les options dont les utilisateurs lorsqu'ils appliquent des modèles à de nouveaux sites et les dispositions vers les nouvelles pages. Lorsque vous choisissez d'appliquer des filtres à un site web hôte dans l'exemple de page de démarrage, l'exemple définit une mise en page personnalisée en tant que valeur par défaut et une mise en page supplémentaires en tant que la seule autre option pour toutes les nouvelles pages créées par un utilisateur. L'exemple réduit également le nombre d'options disponibles pour les utilisateurs lorsqu'ils créent des nouveaux sous-sites. La figure 12 illustre l'aspect de la zone de sélection du modèle de site à la fois avant et après que les filtres ont été appliqués.

La figure 12. Sélection du modèle de site avant et après que les exemples de filtres ont été appliqués.

Sélection du modèle de site avant et après l’application des filtres d’échantillon

L'exemple définit la valeur par défaut et les mises en page disponibles en transmettant les fichiers *.aspx associées à des méthodes pour les méthodes d'extension, comme indiqué dans le code.

                List<string> pageLayouts = new List<string>();
                pageLayouts.Add("ContosoLinksBelow.aspx");
                pageLayouts.Add("ContosoLinksRight.aspx");
                clientContext.Web.SetAvailablePageLayouts(clientContext.Web, pageLayouts);

                // Set default page layout for the site
                clientContext.Web.SetDefaultPageLayoutForSite(clientContext.Web, "ContosoLinksBelow.aspx");

L'exemple définit les modèles de site disponibles en procédant comme quelque chose de similaire. Dans ce cas, il transmet les instances de WebTemplateEntity qui définissent chaque modèle de site à une méthode d'extension appelée SetAvailableWebTemplates.

List<WebTemplateEntity> templates = new List<WebTemplateEntity>();
                templates.Add(new WebTemplateEntity() { LanguageCode = "1035", TemplateName = "STS#0" });
                templates.Add(new WebTemplateEntity() { LanguageCode = "", TemplateName = "STS#0" });
                templates.Add(new WebTemplateEntity() { LanguageCode = "", TemplateName = "BLOG#0" });
                clientContext.Web.SetAvailableWebTemplates(templates);

Les trois de ces méthodes d'extension – SetAvailablePageLayouts, SetDefaultPageLayoutForSiteet SetAvailableWebTemplates – fonctionnent de la même manière. Ils créent des documents XML qui contiennent des paires clé/valeur qui définissent la disposition et mises en page par défaut et les modèles disponibles. Ensuite, elles passent ces documents à une méthode d'extension supplémentaires appelée SetPropertyBagValue. Cette méthode est implémentée dans OfficeDevPnPCore extension. Une fois qu'il configure les conteneurs de propriétés appropriées, ces conteneurs de propriétés sont ensuite utilisés pour filtrer les options dans l'interface.

Des trois méthodes, SetAvailableWebTemplates indique le motif complète.

public static void SetAvailableWebTemplates(this Web web, List<WebTemplateEntity> availableTemplates)
        {
            string propertyValue = string.Empty;

            LanguageTemplateHash languages = new LanguageTemplateHash();
            foreach (var item in availableTemplates)
            {
                AddTemplateToCollection(languages, item);
            }

            if (availableTemplates.Count > 0)
            {
                XmlDocument xd = new XmlDocument();
                XmlNode xmlNode = xd.CreateElement("webtemplates");
                xd.AppendChild(xmlNode);
                foreach (var language in languages)
                {
                    XmlNode xmlLcidNode = xmlNode.AppendChild(xd.CreateElement("lcid"));
                    XmlAttribute xmlAttribute = xd.CreateAttribute("id");
                    xmlAttribute.Value = language.Key;
                    xmlLcidNode.Attributes.SetNamedItem(xmlAttribute);

                    foreach (string item in language.Value)
                    {
                        XmlNode xmlWTNode = xmlLcidNode.AppendChild(xd.CreateElement("webtemplate"));
                        XmlAttribute xmlAttributeName = xd.CreateAttribute("name");
                        xmlAttributeName.Value = item;
                        xmlWTNode.Attributes.SetNamedItem(xmlAttributeName);
                    }
                }
                propertyValue = xmlNode.OuterXml;
            }
            // Save the XML entry to property bag.
            web.SetPropertyBagValue(AvailableWebTemplates, propertyValue);
            // Set that templates are not inherited.
            web.SetPropertyBagValue(InheritWebTemplates, "False");

Le conteneur de propriétés InheritWebTemplates permet de s'assurer que les modèles qui sont normalement héritées du site parent également sont ignorées lorsque vous créez des sous-sites.

Afficher: