Aller plus loin avec les webparts Sharepoint

Dans cet article, grâce à un exemple concret, nous allons voir comment travailler avec des propriétés personnelles dans un webpart ainsi qu'avec les connexions. L'exemple consiste à créer un webpart affichant les posts d'un blog pour gérer le multi-linguisme.

- Titre : Aller plus loin avec les webparts Sharepoint

- Parution : 30 août 2007

- Licence : Ce document est issu de http://www.developpez.com et reste la propriété exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise à l'obtention préalable de l'autorisation de l'auteur.

Sommaire

- I. Introduction

- II. Contexte - Le blog

- III. Notre webpart en images

- IV. L'environnement de développement

- V. Les propriétés personnelles dans un Webpart

- V-A. Conditions à respecter pour exposer des propriétés

- V-B. Les valeurs simples

- V-C. Les valeurs multiples dynamiques

- VI. Les connexions

- VII. Le code

- VII-A. Le webpart en lui-même

- VII-B. Notre toolpart personnel

- VIII. Le déploiement

- VIII-A. Déploiement "manuel"

- VIII-B. Déploiement avec Visual Studio

- VIII-C. Déploiement d'une solution .wsp

- VIII-D. Chargement manuel dans la galerie

- IX. Ajouter la colonne langue dans la liste "Posts" et la rendre obligatoire

- IX-A. Via une colonne "choice"

- IX-B. Via une colonne "lookup"

- X. Utilisation de notre webpart

- X-A. Création du webpart fournisseur

- X-A-1. Via le webpart "Choice Filter"

- X-A-2. Via un webpart "Form"

- X-A-3. Via un webpart de liste

- X-A-4. Insertion de notre webpart sur la page

- X-A-5. Connexion de notre webpart avec le webpart fournisseur

- X-A-6. Le filtre en action

- XI. Téléchargement

- XII. Conclusion

I - Introduction

Le webpart que nous allons créer est destiné à être utilisé dans un blog. Le but est de permettre la gestion de plusieurs langues et de permettre au visiteur de sélectionner les posts correspondants à la langue de son choix. En effet, à l'heure où j'écris cet article, il n'est pas possible d'utiliser le webpart "Posts" standard pour gérer plusieurs langues. Si vous ajoutez une colonne "Langue" dans votre liste "Posts", vous ne pouvez pas l'inclure dans la vue par défaut associée au webpart "Posts". Si vous décidez d'appliquer une vue spécifique à "Posts", vous n'aurez pas le même rendu que celui que vous obtenez avec la vue interne du webpart.

Donc, vous devez soit vous contenter d'un blog dont les posts sont publiés en une seule langue, soit composer avec le fait que l'affichage standard réalisé par le webpart "Posts" n'est plus possible dès lors que vous ajoutez une colonne de metadata stockant la langue.

Le webpart que nous réalisons ici a d'une part un but pédagogique permettant d'appréhender la création de webparts plus complexes et par la même occasion pallie à ce problème et est disponible en téléchargement en bas de l'article. Par ailleurs il ne couvre pas toutes les fonctionnalités du webpart standard et est créé dans l'unique but de gérer facilement plusieurs langues.

Attention!! Si vous téléchargez le projet, veillez à suivre les instructions de la section "Chargement manuel dans la galerie" pour que tout fonctionne correctement

II - Contexte - Le blog

Pour que notre webpart fonctionne correctement, il faut créer un site de type blog. Le webpart "vérifie" qu'il est bien déployé dans un modèle de site blog dès que vous l'ajoutez dans une page. Dans le cas contraire, il vous affiche une erreur stipulant qu'il ne peut être utilisé que dans un blog. Veillez donc à créer votre blog.

III - Notre webpart en images

Pour que vous ayez une idée du résultat fini, voici à quoi ressemble notre webpart. En outre, ce webpart est en activité dans mon blog. Vous pouvez le visualiser ici.

Un exemple de page d'accueil d'un blog combinant notre webpart et un webpart de type "Choice Filter" permettant de sélectionner une langue

Comme vous pouvez le constater, il est possible de déployer/refermer le corps d'un post et bien sûr, il est possible de filtrer sur la langue. Ceci se fait grâce à des propriétés personnelles et à l'implémentation d'une connexion.

Et voici le panneau de propriétés représenté par l'image ci-dessous.

Nous exposons deux propriétés. Une case à cocher (valeur simple booléenne) et une liste déroulante (plusieurs valeurs dynamiques) permettant de spécifier le champ de la liste "Posts" qui stocke la langue et sur lequel il faut filtrer.

IV - L'environnement de développement

Je vous suggère de consulter un un autre tuto qui stipule quels sont les outils de développement disponibles pour les webparts.

V - Les propriétés personnelles dans un Webpart

V-A - Conditions à respecter pour exposer des propriétés

Pour exposer des propriétés personnelles dans le panneau de configuration d'un webpart, vous devez impérativement faire ceci:

- Référencer les espaces de noms System.Xml.Serialization et System.ComponentModel car votre classe doit être sérialisée en XML

- Appliquer les attributs (ToolboxData et XmlRoot) nécessaires à la description et sérialisation de votre classe.

V-B - Les valeurs simples

Pour exposer des propriétés à valeur simple telle qu'une chaîne de caractère, un booléen, un numérique, il suffit de déclarer des propriétés et de préfixer celles-ci avec les attributs permettant de les catégoriser et de les afficher dans le panneau de configuration d'un webpart

Exemple de propriété

public string _LanguageField = null;
[Browsable(false),
Category("Post Settings"),
WebPartStorage(Storage.Personal),
FriendlyName("Language Field"),
Description("Select the column to apply")]
public string LanguageField
{
get
{
return _LanguageField;
}
set
{
_LanguageField = value;
}
}

Attribut

Description

Browsable

Permet de marquer une propriété comme accessible dans le panneau de configuration

Category

Permet de spécifier une catégorie dans laquelle la propriété doit s'afficher

FriendlyName

Permet de spécifier un intitulé à la propriété

Description

Décrit la propriété

DefaultValue

Permet de spécifier une valeur par défaut

Type de valeur

Type de rendu

string, date, numérique (int, long etc...)

zone de texte dans le panneau de propriétés

bool

case à cocher

enum

liste déroulante avec valeurs statiques

Notez qu'une validation automatique est réalisée. Si un utilisateur entre 1.3 pour un int, le système lui dira que cette valeur est invalide et ceci sans le moindre effort de développement.

Pour les types numériques (int, long,double) il faut procéder exactement comme pour la propriété dans l'exemple ci-dessus mais il faut bien sûr remplacer "string" par "int" ou "long" ou "double". Pour une liste déroulante avec valeurs statiques, on peut utiliser une enum. En voici un petit exemple

public enum DemoList
{
Une = 1,
Deux = 2,
Trois = 3,
Quatre = 4
};
protected DemoList _DemoListValues;

[Category("Post Settings")]
[DefaultValue(DemoList.Deux)]
[WebPartStorage(Storage.Personal)]
[FriendlyName("Example")]
[Description("Select a value")]
[Browsable(true)]
public DemoList DemoListValues
{
get
{
return _DemoListValues;
}
set
{
_DemoListValues = value;
}
}

Voici à quoi cela ressemble.

V-C - Les valeurs multiples dynamiques

Pour créer des listes de valeurs dynamiques, vous devez créer un custom toolpart. Voir la section intitulée "Notre toolpart personnel"

VI - Les connexions

Un des aspects qui fait la puissance des webparts est la capacité qu'ils ont à s'inter-connecter afin d'échanger des données. Ceci permet à un webpart de type consommateur d'obtenir une donnée d'un fournisseur. Pour en savoir un peu plus sur les connexions entre webparts, vous pouvez consulter ce tuto (webparts sharepoint) qui est une introduction aux connexions.

Toute une série d'interfaces nous permettent de connecter des webparts entre-eux, en voici une liste non exhaustive ainsi que leur description

Interface

Description

Une interface personnelle

Comme dans l'exemple montré dans mon autre tuto, on peut créer sa propre interface pour spécifier quel type de donnée doit être échangé entre un fournisseur et un consommateur

IWebPartField

Permet d'échanger la valeur d'un champ entre deux webparts

IWebPartRow

S'utilise pour échanger une ligne de donnée (DataRow) d'un webpart vers un autre

IWebPartTable

S'utilise pour échanger une table de données (DataTable) d'un webpart vers un autre

IWebPartParameters

Permet de spécifier les paramètres que l'on souhaite échanger

Dans notre webpart, nous récupérons en paramètre une instance de l'interface IWebPartField car nous souhaitons que la langue soit optionellement fournie par un autre webpart, quel que soit le type de celui-ci. En effet, IWebPartField nous permet de récupérer la donnée d'une colonne de liste, d'un webpart de type filtre ou d'un webpart formulaire. En fait il permet de récupérer une seule donnée quelle que soit sa provenance et pour autant que le webpart fournisseur ait implémenté l'interface IWebPartField. Cette capacité suffit à combler nos besoins.

Voici le code qui nous permet de recevoir une colonne d'un fournisseur

private IWebPartField LanguageProvider; //Will point to the provider
private object ProvidedLanguageValue;//Will hold the value provided by the provider

private void GetFieldValue(object fieldValue)
{
ProvidedLanguageValue = fieldValue;
}

[ConnectionConsumer("FieldConsumer", "LanguageConnectionPoint",
typeof(FieldConsumerConnectionPoint), AllowsMultipleConnections = false)]
public void SetConnectionInterface(IWebPartField provider)
{
LanguageProvider = provider;
}
protected override void OnPreRender(EventArgs e)
{
if (LanguageProvider != null)
{
LanguageProvider.GetFieldValue(new FieldCallback(GetFieldValue));
}
base.OnPreRender(e);
}

et la classe gérant la connexion

public class FieldConsumerConnectionPoint : ConsumerConnectionPoint
{
public FieldConsumerConnectionPoint(MethodInfo callbackMethod,
Type interfaceType, Type controlType, string name, string id,
bool allowsMultipleConnections)
: base(
callbackMethod, interfaceType, controlType,
name, id, allowsMultipleConnections)
{
}

}

Ceci a pour effet d'exécuter le code de la manière suivante:

- Losrqu'une connexion est établie, la méthode SetConnectionInterface s'exécute automatiquement car elle est préfixée de l'attribut ConnectionConsumer et reçoit en paramètre une instance de l'interface IWePartField qui vient du fournisseur. Celui-ci a implémenté la méthode GetFieldValue qui envoie la donnée qu'il a à transmettre au consommateur

- La classe gérant la connexion (FieldConsumerConnectionPoint) appelle le constructeur de la classe de base ConsumerConnectionPoint en lui spécifiant que la méthode de callback est celle reçue en paramètre par setConnectionInterface, en l'occurrence GetFieldValue

- En cas de connexion étabie, la méthode OnPreRender s'assure que la méthode GetFieldValue du fournisseur renvoie la valeur que celui-ci a à transmettre

Lorsque tout ce processus s'est exécuté, la variable ProvidedLanguageValue contient la valeur transmise par le fournisseur.

VII - Le code

VII-A - Le webpart en lui-même

Je ne vais pas reprendre tout le code du webpart car il contient les propriétés (déjà exposées dans les autres sections ) et les méthodes classiques telles que CreateChildControls et Render. Je ne vais reprendre ici que ce qui me semble être intéressant à expliquer.

N'oublions pas que le but de notre webpart est de permettre l'affichage des posts contenus dans la liste "Posts" en fonction d'un filtre optionel sur la langue. En effet, ce filtre sera d'application si une connexion avec un fournisseur est établie, sinon tous les posts sans distinction devront être listés. Pour interroger une liste Sharepoint il faut passer par une CAML Query. Voici la partie permettant de récupérer les posts

SPQuery PostQuery = new SPQuery();
//that query retrieves all the items sorted descendingly on the creation date
PostQuery.Query = "<OrderBy><FieldRef Name=\"Created\" Ascending=\"FALSE\" /></OrderBy>";
if (LanguageField != null)
{
PropertyDescriptor prop = LanguageProvider.Schema;
//If the value provided value isn't null, I create an SPQuery that takes the provided value into account.
if (prop != null && ProvidedLanguageValue != null && ProvidedLanguageValue.ToString().ToLower() != "no filter")
{
StringBuilder SpQueryString = new StringBuilder();
SpQueryString.Append("&lt;OrderBy>&lt;FieldRef Name=\"Created\" Ascending=\"FALSE\" />&lt;/OrderBy>");
SpQueryString.AppendFormat("&lt;Where>&lt;Eq>&lt;FieldRef Name='{0}' />&lt;Value Type='Text'>{1}&lt;/Value>&lt;/Eq>&lt;/Where>",
PostList.Fields[LanguageField].InternalName,//Must use the internal name in CAML queries
ProvidedLanguageValue //contains the value provided by the provider
);
PostQuery.Query = SpQueryString.ToString();
}
}

Donc, la première ligne crée une requête CAML pour récupérer tous les posts triés par ordre de création du dernier au premier. Ensuite, si une connexion est établie et que la valeur transmise par le fournisseur n'est pas nulle ou égale à "No Filter", on crée une requête qui ne récupère que les posts dont la langue est égale à la valeur fournie par le fournisseur.

Note: les requêtes CAML ne sont pas toujours évidentes à écrire. Cependant, il existe divers outils sur le web permettant de les créer plus facilement. En tapant "CAML Query Builder" sur google, vous trouverez pas mal de ressources. J'ai ma propre astuce pour créer les requêtes, si ça vous intéresse, suivez ce lien

Une autre partie du code consiste à parcourir la liste des posts et à les afficher

foreach (SPListItem PostItem in PostList.GetItems(PostQuery))
{
HtmlTable ItemTable = new HtmlTable();
HtmlTableRow ItemRow = new HtmlTableRow();
HtmlTableCell ItemCell = new HtmlTableCell();
.....//d'autres lignes
if (ExpandedEnabled)
{
//If the expanding/collapsing functionality has been activated, I just add an image next to each post title
TitleCellHtml.Append("<img onclick=\"if(this.src.indexOf('minus') != -1){");
TitleCellHtml.Append("this.parentNode.parentNode.parentNode.rows[1].style.display='none';");
TitleCellHtml.Append("this.src='_layouts/images/plus.gif';}");
TitleCellHtml.Append("else{this.parentNode.parentNode.parentNode.rows[1].style.display='';");
TitleCellHtml.Append("this.src='_layouts/images/minus.gif';}\" src='_layouts/images/minus.gif'/>&nbsp;");
}
.....//d'autres lignes
}

Le code ci-dessus parcourt la liste des posts et si la propriété "ExpandedEnabled" est mise à true, le javascript nécessaire à l'ouverture/fermeture du corps du post est généré.

VII-B - Notre toolpart personnel

Un toolpart sert à exposer une propriété plus complexe telle qu'une liste déroulante contenant des valeurs dynamiques issues d'une liste Sharepoint par exemple ou d'une base de données. On peut également exposer des formulaires de saisie, des popups etc...

Pour créer un toolpart, vous devez simplement ajouter une classe à votre projet

Dans notre exemple, nous avons développé un toolpart qui sert à afficher une zone de liste avec les colonnes de la liste "Posts" afin de permettre à l'utilisateur de sélectionner la colonne qui représente la langue et donc celle sur laquelle il faut filtrer les posts. Voici le code qui a servi à cela

using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebPartPages;

namespace MultiLingualPost
{
class FieldList : Microsoft.SharePoint.WebPartPages.ToolPart
{
MultiLingualPost ParentWp = null;
Label ErrorMessage = null;
public FieldList()
{
this.Title = "Language Field";
}
public override void ApplyChanges()
{
string FieldName = Page.Request.Form["LanguageField"];
ParentWp = (MultiLingualPost)this.ParentToolPane.SelectedWebPart;
ParentWp.LanguageField = FieldName;
}
protected override void CreateChildControls()
{
ErrorMessage = new Label();
ErrorMessage.Style.Add(HtmlTextWriterStyle.Color, "red");
this.Controls.Add(ErrorMessage);
}
/// <summary>
///    If the ApplyChanges method succeeds, this method is called by the tool pane
///    to refresh the specified property values in the toolpart user interface.
/// </summary>
public override void SyncChanges()
{
// sync with the new property changes here
}

/// <summary>
///    Called by the tool pane if the user discards changes to the selected Web Part.
/// </summary>
public override void CancelChanges()
{
}

protected override void RenderToolPart(HtmlTextWriter output)
{
//LanguageField is a HTML list that will contain all the columns belonging to the "Post" list.
ParentWp = (MultiLingualPost)this.ParentToolPane.SelectedWebPart;
output.Write("<select name='LanguageField'>");
try
{

//Getting the columns of the "Posts" list
foreach (SPField ListField in SPContext.Current.Web.Lists["Posts"].Fields)
{

if (ParentWp.LanguageField != ListField.Title)
{
output.Write("<option>" + ListField.Title + "</option>");
}
else
{
output.Write("<option selected>" + ListField.Title + "</option>");
}

}

}
catch (Exception e)
{
ErrorMessage.Text = e.Message;
}

output.Write("</select>");
ErrorMessage.RenderControl(output);
}
}
}

Voici en détail, méthode par méthode ce que ce code fait

Méthode

Description

FieldList

Constructeur dans lequel on affecte un titre à notre toolpart

ApplyChanges

Cette méthode est appelée lorsque l'utilisateur clique sur "Apply" ou "Ok". Une référence vers notre webpart principal est réalisée et on attribue la valeur saisie à la propriété du webpart principal

CreateChildControls

Comme dans un webpart, on peut utiliser cette méthode si l'on travaille avec des WebControls. C'est une méthode optionelle

SyncChanges

Cette méthode est appelée lorsque la méthode ApplyChanges s'est exécutée avec succès. Elle permet de raffraîchir le toolpane.

CancelChanges

Cette méthode est appelée lorsque l'utilisateur annule ses changements. Si vous desirez intervenir en cas d'annulation, c'est via cette méthode que vous pourrez le faire

RenderToolPart

Permet d'afficher notre toolpart. Il est à noter que deux techniques sont possibles. Soit vous écrivez directement le HTML vous-même, soit vous passez par des HtmlControls et/ou des WebControls et vous utilisez leur méthode "RenderControl" pour qu'ils soient convertis en HTML par le système.

Pour que notre toolpart soit correctement appelé, vous devez implémenter la méthode GetToolParts

public override ToolPart[] GetToolParts()
{
ToolPart[] toolparts = new ToolPart[3];
WebPartToolPart wptp = new WebPartToolPart();
CustomPropertyToolPart custom = new CustomPropertyToolPart();
toolparts[0] = custom;
toolparts[1] = wptp;
toolparts[2] = new FieldList(); //Language field is called from here
return toolparts;
}

Vous l'aurez compris, un toolpart ressemble fort à un webpart dans un webpart. C'est à vous de produire le code qui servira à générer le HTML de sortie. Si vous désirez produire un formulaire plus riche, rien ne vous empêche de joindre une page HTML et/ou ASPX à votre projet et de l'ouvrir via du javascript (window.open) dans votre toolpane.

VIII - Le déploiement

VIII-A - Déploiement "manuel"

Il est toujours intéressant de savoir comment déployer un webpart manuellement dans la mesure où l'on ne dispose pas toujours de tous les outils nécessaires dans un environnement donné. Suivez ce tuto pour savoir comment cela fonctionne. Vous aurez des informations sur le déploiement en GAC, la configuration du web.config de votre WSS/MOSS etc... Il est à noter qu'un déploiement en GAC n'est pas obligatoire. Placer la dll de votre webpart dans le répertoire bin de votre installation WSS/MOSS peut suffire mais attention aux exceptions que vous pourriez rencontrer concernant la sécurité (CAS code access security de Microsoft)

VIII-B - Déploiement avec Visual Studio

Pour notre webpart, j'ai opté pour cette option. Le modèle WebPart de visual studio permet un déploiement automatique vers un serveur Sharepoint. Voici quelques écrans montrant comment ceci fonctionne

Le serveur Sharepoint vers lequel on désire déployer le webpart est pointé par "Start Browser with URL"

Pour paramétrer les informations telles que le nom de votre webpart, sa description etc.. vous pouvez utiliser l'onglet Solution

Enfin, pour déployer le webpart vers le serveur Sharepoint, vous devez simplement cliquer sur "Deploy"

VIII-C - Déploiement d'une solution .wsp

Les fichiers de solution .wsp sont très pratiques car ils peuvent être aisément déployés vers un serveur Sharepoint en utilisant l'outil stsadm présent dans le répertoire bin de votre installation Sharepoint. Via deux commandes, vous pouvez ajouter et déployer une solution comme ceci

- stsadm -o addsolution filename nomdevotresolution.wsp

- stsadm -o deploysolution -name nomdevotresolution.wsp -allcontenturls -local -allowgacdeployment

Les paramètres -allcontenturls et -allowgacdeployment varient en fonction de ce que vous souhaitez faire.

Le modèle de Webpart de visual studio crée un fichier de solution (.wsp) dans le répertoire debug/bin ou release/bin de votre projet. Vous pouvez donc récupérer celui-ci si vous souhaitez fournir votre solution à quelqu'un ou la déployer vers un serveur en particulier. Ce modèle crée également un fichier "setup.bat" que vous pouvez utiliser pour installer/désinstaller votre solution. Vous pouvez l'éditer pour voir les différents paramètres offerts par ce fichier bat.

VIII-D - Chargement manuel dans la galerie

Le modèle de Webpart de visual studio permet le déploiement automatique et complet sur un serveur sharepoint mais attention car celui-ci se base sur le fait que votre classe principale dérive de System.Web.UI.WebControls.WebParts.WebPart et non de Microsoft.SharePoint.WebPartPages.WebPart. Le webpart est donc déployé avec une extension .webpart et non .dwp. Lorsque vous implémentez un custom toolpart, vous devez dériver de Microsoft.SharePoint.WebPartPages.WebPart pour pouvoir implémenter la méthode GetToolParts or, le problème est que le système déploie quand même le webpart avec une extension .webpart, ce qui fait que quand vous souhaitez l'ajouter, vous obtenez ceci.

Moralité: soit vous laissez tomber le custom toolpart, soit vous devez manuellement charger votre webpart dans la galerie pour bénéficier du format .dwp. Pour savoir comment charger le webpart manuellement dans la galerie, suivez ce tuto. Je ne connais pour l'instant aucune alternative. Merci de me signaler par MP si vous connaissez une solution moins laborieuse.

IX - Ajouter la colonne langue dans la liste "Posts" et la rendre obligatoire

IX-A - Via une colonne "choice"

Pour insérer la colonne langue, procédez comme suit

- Allez sur votre blog et cliquez sur "View All Site Content" ou "Afficher tout le contenu du site"

- Cliquez sur la liste "Posts"

- Cliquez sur "Settings" et ensuite sur "Create Column"

Vous obtenez l'écran suivant:

Nommez la colonne comme vous voulez, rendez-la obligatoire, insérez les langues désirées et cliquez sur ok.

IX-B - Via une colonne "lookup"

Le procédé est le même que pour une colonne de type "Choice" à ceci près que la colonne "Lookup" cherche dans une autre liste la source de données. Vous pourriez donc créer une liste de langues et créer ensuite une colonne lookup pointant sur cette liste.

Lorsque vous aurez ajouté la colonne, vous serez obligé de la renseigner en créant un nouveau post.

X - Utilisation de notre webpart

Si vous avez bien inséré la colonne "Langue" dans la liste comme expliqué dans la section précédente, vous êtes désormais prêt à utiliser le webpart. Rappelez-vous que notre webpart n'est "que" consommateur, il a donc besoin de recevoir la langue d'un autre webpart.

X-A - Création du webpart fournisseur

X-A-1 - Via le webpart "Choice Filter"

Le webpart "Choice Filter" permet de créer facilement une liste de choix accessible pour l'utilisateur. Pour l'ajouter, allez sur votre page principale de blog et cliquez sur "Edit Page". Ensuite, ajoutez le webpart "Choice Filter" comme illustré ci-dessous

Ensuite, configurez-le et ajoutez les différentes langues possibles comme illustré ci-dessous

Cliquez sur "Ok", le webpart vous dit qu'il n'est pas connecté. Laissez-le comme cela pour l'instant

X-A-2 - Via un webpart "Form"

Le principe est le même que pour le choice filter (éditez la page, ajoutez le webpart, allez dans les propriétés), mais vous devez taper le code html de votre formulaire. Cliquez sur le bouton "Source Editor" et insérez-y le code suivant

<select name="language" onchange="javascript:_SFSUBMIT_"/><option>No Filter</option><option>FR</option><option>EN</option></select>

Ceci vous donnera ce résultat:

X-A-3 - Via un webpart de liste

Si vous avez créé une liste "Langues" dans laquelle vous avez encodé toutes les langues possibles et qu'ensuite vous avez créé une colonne de type "lookup" dans la liste "Posts" qui pointe vers la liste "Langues", vous pouvez utiliser la liste "Langues" comme fournisseur pour filtrer sur la langue.

X-A-4 - Insertion de notre webpart sur la page

Pour insérer notre webpart sur la page, procédez comme expliqué dans les sections précédentes mais en choisissant notre webpart. Ensuite, par défaut il devrait déjà afficher tous les posts contenus dans votre liste "Posts".

X-A-5 - Connexion de notre webpart avec le webpart fournisseur

Avant de pouvoir connecter notre webpart de manière fiable, vous devez avoir préalablement spécifié quel est la colonne de la liste "Posts" qui stocke la langue. Pour ce faire, allez dans les propriétés du webpart et choisissez la colonne dans la zone de liste (vous devez bien sûr l'avoir créée avant dans la liste "Posts")

Lorsque ceci est fait, vous pouvez désormais connecter le webpart avec votre fournisseur (dans notre exemple, c'est soit un choice filter, soit un form webpart). Prenons le cas le plus simple du choice filter. Vous devez procéder comme illustré ci-dessous:

La connexion devrait être établie à présent. Vous pouvez le voir car le choice filter l'indiquera

X-A-6 - Le filtre en action

Lorsque vous avez procédé à toutes les étapes ci-dessus, vous êtes en mesure de visualiser vos posts de manière standard tout en bénéficiant de la possibilité de les filtrer sur la langue via votre choice filter ou votre form webpart.

XI - Téléchargement

Si vous souhaitez juste installer le webpart sur votre serveur, utilisez le fichier setup.bat présent dans le répertoire debug/bin. Veillez à spécifier l'URL de votre serveur Sharepoint. Procédez ensuite au chargement manuel du webpart dans la galerie comme expliqué dans la section "Chargement manuel dans la galerie".

Voici le projet MultiLingualWebPart

XII - Conclusion

Avec cet article nous aurons vu les bases concernant les connexions de webpart et comment créer des propriétés personnelles avancées. Il va de soi que le webpart développé est perfectible. Je compte l'utliser sur mon blog dans un futur proche, il subira donc certainement quelques mises à jour. La version actuellement disponible en téléchargement est vraiment "un premier jet". J'ai mis plus de temps à écrire cet article qu'à effectuer le développement :), libre à vous d'aller plus loin.