Procédure pas à pas : création d'un type de champ personnalisé
Dernière modification : vendredi 25 juin 2010
S’applique à : SharePoint Foundation 2010
Dans cet article
Configuration du projet
Création de la classe de règle de validation
Création de la classe de champ personnalisé
Création du contrôle de rendu de champ
Création du modèle de rendu de champ
Création de la définition de type de champ
Création de la feuille de style XSLT
Générer et tester le type de champ personnalisé
Différences de rendu des champs entre les périphériques mobiles et les ordinateurs
Cette rubrique vous guide pas à pas dans la création d’un type de champ personnalisé. Vous allez créer un champ destiné à contenir un numéro ISBN (International Standard Book Number) de 10 chiffres.
Pour une présentation des étapes impliquées dans la création d’un type de champ personnalisé et dans la définition de son affichage, voir Procédure : créer un type de champ personnalisé.
Conditions requises
Microsoft Visual Studio 2010
Configuration du projet
Pour configurer le projet de champ personnalisé
Dans Visual Studio, créez un Projet SharePoint vide. Définissez-le en tant que solution de batterie, et non comme solution en bac à sable (sandboxed) ; puis, nommez-le ISBN_Field_Type.
Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le nom du projet et sélectionnez Propriétés.
Sous l’ongletApplication de la boîte de dialogue Propriétés, entrez Contoso.SharePoint.ISBN_Field_Type comme Nom d’assembly et Contoso.SharePoint comme Espace de noms par défaut. Laissez Version cible avec la valeur .NET Framework 3.5.
Si la zone Plateformes Solution du Menu standardVisual Studio ne mentionne pas « Any CPU » ou « x64 », ouvrez l’onglet Créer et définissez la Plateforme cible avec la valeur « Any CPU » ou « x64 ». Pour plus d’informations sur le choix proposé, voir Procédure : définir le Framework et l’unité centrale cibles adéquats.
Cliquez sur le bouton Enregistrer tout de la barre d’outils.
Cliquez avec le bouton droit sur le nom du projet dans l’Explorateur de solutions, puis sélectionnez Ajouter, Nouvel élément.
Dans la boîte de dialogue Ajouter un nouvel élément, sélectionnez Visual C#, Code (ou Visual Basic, Code) dans l’arborescence Modèles installés.
Sélectionnez Classe dans la zone Modèles, puis entrez ISBN.Field.cs (ou ISBN.Field.vb) dans la zone Nom. Cliquez sur Ajouter.
Répétez l’étape précédente pour créer la deuxième classe, mais entrez ISBN.FieldControl.cs (ou ISBN.FieldControl.vb) dans la zone Nom. Cliquez sur Ajouter.
Ajoutez une troisième classe de la même façon et entrez ISBN10ValidationRule.cs (ou ISBN10ValidationRule.vb) dans la zone Nom. Cliquez sur Ajouter.
Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le nom du projet et sélectionnez Ajouter, puis Dossier mappé SharePoint.
Utilisez le contrôle d’arborescence qui s’affiche pour mapper le dossier avec TEMPLATE\ControlTemplates, puis cliquez sur OK.
Cliquez avec le bouton droit sur le nouveau dossier ControlTemplates (pas sur le nom du projet) dans l’Explorateur de solutions, puis sélectionnez Ajouter, Nouvel élément.
Dans la boîte de dialogue Ajouter un nouvel élément, sélectionnez SharePoint, 2010 dans l’arborescence Modèles installés.
Sélectionnez un Contrôle utilisateur SharePoint dans la zone Modèles et attribuez au fichier ascx le nom ISBNFieldControl.ascx. Cliquez sur Ajouter. Visual Studio ajoute automatiquement le fichier au manifeste de la solution SharePoint Solution et définit son déploiement sur %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\TEMPLATE\ControlTemplates. Il ajoute également l’assembly au manifeste et définit son déploiement sur le Global Assembly Cache (GAC).
Conseil
N’ajoutez pas le Contrôle utilisateur en cliquant avec le bouton droit sur le nom du projet dans l’Explorateur de solutions. Quand un Contrôle utilisateur est ajouté de cette façon, Visual Studio le place dans un sous-dossier de TEMPLATE\ControlTemplates et, s’il n’est pas déplacé, Visual Studio le déploiera dans un sous-dossier correspondant de %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\TEMPLATE\ControlTemplates. Les modèles de rendu des sous-dossiers ne sont pas chargés.
Supprimez les fichiers ISBNFieldControl.ascx.cs et ISBNFieldControl.ascx.designer.cs (ou les fichiers ISBNFieldControl.ascx.vb et ISBNFieldControl.ascx.designer.vb) qui sont créés automatiquement sous le fichier ISBNFieldControl.ascx. Ils ne sont pas nécessaires pour ce projet. Le contenu par défaut de ISBNFieldControl.ascx se rapporte au fichier ISBNFieldControl.ascx.cs (ou ISBNFieldControl.ascx.vb) que vous venez de supprimer et, si vous générez le projet à ce stade, le compilateur affiche un avertissement relatif au fichier manquant. Ignorez l’avertissement : le contenu par défaut est modifié dans une étape ultérieure du présent article.
Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le nom du projet, sélectionnez Ajouter, puis Dossier mappé SharePoint.
Utilisez le contrôle d’arborescence qui s’affiche pour mapper le dossier avec TEMPLATE\XML, puis cliquez sur OK.
Cliquez avec le bouton droit sur le nouveau dossier XML (pas sur le nom du projet) dans l’Explorateur de solutions, puis sélectionnez Ajouter, Nouvel élément.
Dans la boîte de dialogue Ajouter un nouvel élément, sélectionnez Visual C#, Données (ou Visual Basic, Données), puis Fichier XML dans la fenêtre Modèles.
Dans la zone Nom, tapez fldtypes_ISBNField.xml et cliquez sur Ajouter.
Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le nom du projet, sélectionnez Ajouter, puis Dossier mappé SharePoint.
Utilisez le contrôle d’arborescence qui s’affiche pour mapper le dossier avec TEMPLATE\LAYOUTS\XSL, puis cliquez sur OK.
Cliquez avec le bouton droit sur le nouveau dossier XSL (pas sur le nom du projet) dans l’Explorateur de solutions, puis sélectionnez Ajouter, Nouvel élément.
Dans la boîte de dialogue Ajouter un nouvel élément, sélectionnez Visual C#, Données (ou Visual Basic, Données), puis Fichier XSLT dans la fenêtre Modèles.
Dans la zone Nom, tapez fldtypes_ISBNField.xsl et cliquez sur Ajouter. Notez que le nom est très similaire à celui du précédent fichier que vous avez créé. Les deux fichiers ont des objectifs différents et sont déployés dans des dossiers distincts. Conservez-les tels quels tandis que vous étudiez le présent article.
Cliquez avec le bouton droit sur le nœud Références de l’Explorateur de solutions, cliquez sur Ajouter une référence, puis sélectionnez PresentationFramework.dll sous l’onglet .NET de la boîte de dialogue Ajouter une référence. Cliquez sur OK. (Cet assembly contient la définition de la classe ValidationRule que vous créerez dans la prochaine procédure.)
Création de la classe de règle de validation
Pour créer une classe de règle de validation
Ouvrez le fichier ISBN10ValidationRule.cs (ou ISBN10ValidationRule.vb) et ajoutez les instructions suivantes.
using System.Text.RegularExpressions; using System.Windows.Controls; using System.Globalization;
Imports System.Text.RegularExpressions Imports System.Windows.Controls Imports System.Globalization
Modifiez l’espace de noms afin de respecter les instructions définies dans les Conventions de dénomination des espaces de noms (éventuellement en anglais). Dans cette procédure, utilisez Contoso.System.Windows.Controls.
Remplacez la déclaration de classe par le code suivant :
public class ISBN10ValidationRule : ValidationRule { private const Int32 ISBNMODULO = 11; public override ValidationResult Validate(object value, CultureInfo cultureInfo) { String iSBN = (String)value; String errorMessage = ""; Regex rxISBN = new Regex(@"^(?'GroupID'\d{1,5})-(?'PubPrefix'\d{1,7})-(?'TitleID'\d{1,6})-(?'CheckDigit'[0-9X]{1})$"); if (!rxISBN.IsMatch(iSBN)) { errorMessage = "An ISBN must have this structure:\n1-5 digit Group ID, hyphen, \n1-7 digit Publisher Prefix, hyphen, \n1-6 digit Title ID, hyphen, \n1 Check Digit (which can be \"X\" to indicate \"10\").\n"; } if (errorMessage == "") // Matched the RegEx, so check for group length errors. { Match mISBN = rxISBN.Match(iSBN); GroupCollection groupsInString = mISBN.Groups; String groupID = groupsInString["GroupID"].Value; String pubPrefix = groupsInString["PubPrefix"].Value; if ((groupID.Length + pubPrefix.Length) >= 9) { errorMessage = "The Group ID and Publisher Prefix can total no more than 8 digits.\n"; } String titleID = groupsInString["TitleID"].Value; if (((groupID.Length + pubPrefix.Length) + titleID.Length) != 9) { errorMessage = errorMessage + "The Group ID, Publisher Prefix, and \nTitle ID must total exactly 9 digits.\n"; } if (errorMessage == "") //No group length errors, so verify the check digit algorithm. { Int32 checkDigitValue; String checkDigit = groupsInString["CheckDigit"].Value; // To ensure check digit is one digit, "10" is represented by "X". if (checkDigit == "X") { checkDigitValue = 10; } else { checkDigitValue = Convert.ToInt32(checkDigit); } String iSBN1st3Groups = groupID + pubPrefix + titleID; //Concatenate without the hyphens. // Sum the weighted digits. Int32 weightedSum = (10 * Convert.ToInt32(iSBN1st3Groups.Substring(0, 1))) + (9 * Convert.ToInt32(iSBN1st3Groups.Substring(1, 1))) + (8 * Convert.ToInt32(iSBN1st3Groups.Substring(2, 1))) + (7 * Convert.ToInt32(iSBN1st3Groups.Substring(3, 1))) + (6 * Convert.ToInt32(iSBN1st3Groups.Substring(4, 1))) + (5 * Convert.ToInt32(iSBN1st3Groups.Substring(5, 1))) + (4 * Convert.ToInt32(iSBN1st3Groups.Substring(6, 1))) + (3 * Convert.ToInt32(iSBN1st3Groups.Substring(7, 1))) + (2 * Convert.ToInt32(iSBN1st3Groups.Substring(8, 1))) + checkDigitValue; Int32 remainder = weightedSum % ISBNMODULO; // ISBN is invalid if weighted sum modulo 11 is not 0. if (remainder != 0) { errorMessage = "Number fails Check Digit verification."; } if (errorMessage == "") // Passed check digit verification. { return new ValidationResult(true, "This is a valid ISBN."); }// end check digit verification passed else // the check digit verification failed { return new ValidationResult(false, errorMessage); } }// end no group length errors else // There was some error in a group length { return new ValidationResult(false, errorMessage); } }// end RegEx match succeeded else // There was a RegEx match failure { return new ValidationResult(false, errorMessage); } }// end Validate method }// end ISBN10ValidationRule class
Public Class ISBN10ValidationRule Inherits ValidationRule Private Const ISBNMODULO As Int32 = 11 Public Overrides Function Validate(ByVal value As Object, ByVal cultureInfo As CultureInfo) As ValidationResult Dim iSBN As String = CType(value, String) Dim errorMessage As String = "" Dim rxISBN As New Regex("^(?'GroupID'\d{1,5})-(?'PubPrefix'\d{1,7})-(?'TitleID'\d{1,6})-(?'CheckDigit'[0-9X]{1})$") If Not rxISBN.IsMatch(iSBN) Then errorMessage = "An ISBN must have this structure:" & vbLf & "1-5 digit Group ID, hyphen, " & vbLf & "1-7 digit Publisher Prefix, hyphen, " & vbLf & "1-6 digit Title ID, hyphen, " & vbLf & "1 Check Digit (which can be ""X"" to indicate ""10"")." & vbLf End If If errorMessage = "" Then ' Matched the RegEx, so check for group length errors. Dim mISBN As Match = rxISBN.Match(iSBN) Dim groupsInString As GroupCollection = mISBN.Groups Dim groupID As String = groupsInString("GroupID").Value Dim pubPrefix As String = groupsInString("PubPrefix").Value If (groupID.Length + pubPrefix.Length) >= 9 Then errorMessage = "The Group ID and Publisher Prefix can total no more than 8 digits." & vbLf End If Dim titleID As String = groupsInString("TitleID").Value If ((groupID.Length + pubPrefix.Length) + titleID.Length) <> 9 Then errorMessage = errorMessage & "The Group ID, Publisher Prefix, and " & vbLf & "Title ID must total exactly 9 digits." & vbLf End If If errorMessage = "" Then 'No group length errors, so verify the check digit algorithm. Dim checkDigitValue As Int32 Dim checkDigit As String = groupsInString("CheckDigit").Value ' To ensure check digit is one digit, "10" is represented by "X". If checkDigit = "X" Then checkDigitValue = 10 Else checkDigitValue = Convert.ToInt32(checkDigit) End If Dim iSBN1st3Groups As String = groupID & pubPrefix & titleID 'Concatenate without the hyphens. ' Sum the weighted digits. Dim weightedSum As Int32 = (10 * Convert.ToInt32(iSBN1st3Groups.Substring(0, 1))) + (9 * Convert.ToInt32(iSBN1st3Groups.Substring(1, 1))) + (8 * Convert.ToInt32(iSBN1st3Groups.Substring(2, 1))) + (7 * Convert.ToInt32(iSBN1st3Groups.Substring(3, 1))) + (6 * Convert.ToInt32(iSBN1st3Groups.Substring(4, 1))) + (5 * Convert.ToInt32(iSBN1st3Groups.Substring(5, 1))) + (4 * Convert.ToInt32(iSBN1st3Groups.Substring(6, 1))) + (3 * Convert.ToInt32(iSBN1st3Groups.Substring(7, 1))) + (2 * Convert.ToInt32(iSBN1st3Groups.Substring(8, 1))) + checkDigitValue Dim remainder As Int32 = weightedSum Mod ISBNMODULO ' ISBN is invalid if weighted sum modulo 11 is not 0. If remainder <> 0 Then errorMessage = "Number fails Check Digit verification." End If If errorMessage = "" Then ' Passed check digit verification. Return New ValidationResult(True, "This is a valid ISBN.") ' end check digit verification passed Else ' the check digit verification failed Return New ValidationResult(False, errorMessage) End If ' end no group length errors Else ' There was some error in a group length Return New ValidationResult(False, errorMessage) End If ' end RegEx match succeeded Else ' There was a RegEx match failure Return New ValidationResult(False, errorMessage) End If End Function ' end Validate method End Class ' end ISBN10ValidationRule class
La classe de règle de validation que vous venez de créer contient toute la logique de validation détaillée. Pour plus d'informations sur les classes de règle de validation, voir System.Text.RegularExpressions et ValidationRule.
Création de la classe de champ personnalisé
Pour créer une classe de champ personnalisé
Ouvrez le fichier ISBN.Field.cs (ou ISBN.Field.vb).
Ajoutez les instructions suivantes.
using Microsoft.SharePoint; using Microsoft.SharePoint.WebControls; using Microsoft.SharePoint.Security; using System.Windows.Controls; using System.Globalization; using System.Runtime.InteropServices; using System.Security.Permissions;
Imports Microsoft.SharePoint Imports Microsoft.SharePoint.WebControls Imports Microsoft.SharePoint.Security Imports System.Windows.Controls Imports System.Globalization Imports System.Runtime.InteropServices Imports System.Security.Permissions
Ajoutez les instructions suivantes. Celles-ci permettent à l’implémentation de votre classe de référencer les autres classes que vous créerez dans les étapes ultérieures. Jusqu’à ce que ces classes soient créées, il se peut que le compilateur affiche des avertissements relatifs à ces instructions.
using Contoso.SharePoint.WebControls; using Contoso.System.Windows.Controls;
Imports Contoso.SharePoint.WebControls Imports Contoso.System.Windows.Controls
Vérifiez que l’espace de noms est bien Contoso.SharePoint.
Assurez-vous que la classe se nomme ISBNField et modifiez sa déclaration afin qu’elle hérite de SPFieldText.
public class ISBNField : SPFieldText { }
Public Class ISBNField Inherits SPFieldText End Class
Ajoutez les constructeurs obligatoires suivants pour la classe.
public ISBNField(SPFieldCollection fields, string fieldName) : base(fields, fieldName) { } public ISBNField(SPFieldCollection fields, string typeName, string displayName) : base(fields, typeName, displayName) { }
Public Sub New(fields as SPFieldCollection, fieldname as String) MyBase.New(fields, fieldName) End Sub Public Sub New(fields as SPFieldCollection, typeName as String, displayName as String) MyBase.New(fields, typeName, displayName) End Sub
Ajoutez la substitution suivante de la propriété FieldRenderingControl à la classe. ISBNFieldControl est une classe que vous créerez dans une étape ultérieure.
public override BaseFieldControl FieldRenderingControl { [SharePointPermission(SecurityAction.LinkDemand, ObjectModel = true)] get { BaseFieldControl fieldControl = new ISBNFieldControl(); fieldControl.FieldName = this.InternalName; return fieldControl; } }
Public Overrides ReadOnly Property FieldRenderingControl() As BaseFieldControl Get Dim fieldControl As BaseFieldControl = New ISBNFieldControl() fieldControl.FieldName = Me.InternalName Return fieldControl End Get End Property
Ajoutez la substitution suivante de la méthode GetValidatedString à la classe ISBNField :
public override string GetValidatedString(object value) { if ((this.Required == true) && ((value == null) || ((String)value == ""))) { throw new SPFieldValidationException(this.Title + " must have a value."); } else { ISBN10ValidationRule rule = new ISBN10ValidationRule(); ValidationResult result = rule.Validate(value, CultureInfo.InvariantCulture); if (!result.IsValid) { throw new SPFieldValidationException((String)result.ErrorContent); } else { return base.GetValidatedString(value); } } }// end GetValidatedString
Public Overrides Function GetValidatedString(ByVal value As Object) As String If (Me.Required = True) AndAlso ((value Is Nothing) OrElse (CType(value, String) = "")) Then Throw New SPFieldValidationException(Me.Title & " must have a value.") Else Dim rule As New ISBN10ValidationRule() Dim result As ValidationResult = rule.Validate(value, cultureInfo.InvariantCulture) If Not result.IsValid Then Throw New SPFieldValidationException(CType(result.ErrorContent, String)) Else Return MyBase.GetValidatedString(value) End If End If End Function ' end GetValidatedString
Cette substitution illustre un modèle commun pour les substitutions de GetValidatedString :
Les substitutions de la méthode GetValidatedString vérifient si le champ est obligatoire et, le cas échéant, la méthode substituée lève un exception SPFieldValidationException lorsque la valeur est null ou une String vide. Cette exception est interceptée par les pages Nouvel élément et Modifier l'élément si l'utilisateur essaie d'enregistrer l'élément de liste en cours de création ou de modification. Dans ce cas, la page reste ouverte et la propriété Message() de l'exception entraîne l'apparition d'un message d'erreur sous le champ vide.
Les substitutions de GetValidatedString lèvent une SPFieldValidationException lorsque la valeur n'est pas valide, entraînant l'apparition d'un message d'erreur sous le champ non valide.
Les substitutions de GetValidatedString appellent ensuite le GetValidatedString de base, si la valeur passe la validation personnalisée.
Enregistrez et fermez le fichier.
Création du contrôle de rendu de champ
Pour créer le contrôle de rendu de champ
Ouvrez le fichier ISBN.FieldControl.cs (ou ISBN.FieldControl.vb).
Ajoutez les instructions suivantes.
using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.Runtime.InteropServices; using Microsoft.SharePoint; using Microsoft.SharePoint.WebControls;
Imports System.Web Imports System.Web.UI Imports System.Web.UI.WebControls Imports System.Runtime.InteropServices Imports Microsoft.SharePoint Imports Microsoft.SharePoint.WebControls
Modifiez l’espace de noms en Contoso.SharePoint.WebControls.
Vérifiez que la classe se nomme ISBNFieldControl et modifiez sa déclaration pour spécifier qu’elle hérite de TextField.
public class ISBNFieldControl : TextField { }
Public Class ISBNFieldControl Inherits TextField End Class
Ajoutez un champ protégé pour un contrôle Web Label ASP.NET qui ajoutera le préfixe ISBN devant chaque numéro ISBN qui est rendu en mode Création ou Édition. Il n’est pas nécessaire d’ajouter un champ TextBox protégé pour le numéro ISBN lui-même, car le contrôle ISBNFieldControl personnalisé hérite le champ de TextField.
protected Label ISBNPrefix;
Protected Label ISBNPrefix
Ajoutez un autre champ protégé pour un contrôle Web Label ASP.NET qui restituera la valeur courante du champ en mode Affichage.
protected Label ISBNValueForDisplay;
Protected Label ISBNValueForDisplay
Puis, ajoutez la substitution suivante de la propriété DefaultTemplateName. La valeur String que vous attribuez à cette propriété est l’ID d’un objet RenderingTemplate que vous ajouterez, dans une étape ultérieure, au fichier .ascx que vous avez créé précédemment. (Lorsque votre projet est terminé, ce fichier est déployé sur le dossier %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\TEMPLATE\CONTROLTEMPLATES.) Si aucune des propriétés ControlTemplate, Template ou TemplateName n’est substituée, RenderingTemplate sera appelé de la façon suivante : ControlTemplate renverra Template, qui, à son tour, renverra la propriété Template de quelque objet RenderingTemplate que ce soit nommé par TemplateName. Enfin, l’accesseur get de TemplateName renverra DefaultTemplateName. Dans un cas plus complexe où, par exemple, vous disposez de modèles distincts pour les modes Création et Édition, vous devrez substituer une ou plusieurs des précédentes propriétés, ainsi que, probablement, les propriétés AlternateTemplateName ou DefaultAlternateTemplateName.
protected override string DefaultTemplateName { get { if (this.ControlMode == SPControlMode.Display) { return this.DisplayTemplateName; } else { return "ISBNFieldControl"; } } }
Protected Overrides ReadOnly Property DefaultTemplateName() As String Get If Me.ControlMode = SPControlMode.Display Then Return Me.DisplayTemplateName Else Return "ISBNFieldControl" End Get End Property
Ajoutez la substitution suivante de DisplayTemplateName. La valeur String que vous attribuez à cette propriété est l’ID d’un objet RenderingTemplate que vous ajouterez, dans une étape ultérieure, au fichier ascx que vous avez créé précédemment. Cet objet restitue la valeur du champ en mode Affichage.
public override string DisplayTemplateName { get { return "ISBNFieldControlForDisplay"; } set { base.DisplayTemplateName = value; } }
Public Overrides Property DisplayTemplateName() As String Get Return "ISBNFieldControlForDisplay" End Get Set MyBase.DisplayTemplateName = Value End Set End Property
Ajoutez la substitution suivante de la méthode CreateChildControls. La substitution n’effectue aucune fonction si le ISBNField sous-jacent est null. (Il peut être null si le ISBNFieldControl est créé indépendamment de l’accesseur set de la propriété FieldRenderingControl de ISBNField – voir la substitution de FieldRenderingControl dans ISBN.Field.cs [ou ISBN.Field.vb].)
protected override void CreateChildControls() { if (this.Field != null) { }// end if there is a non-null underlying ISBNField // Do nothing if the ISBNField is null. }
Protected Overrides Sub CreateChildControls() If Me.Field IsNot Nothing Then End If ' end if there is a non-null underlying ISBNField ' Do nothing if the ISBNField is null or control mode is Display. End Sub
Ajoutez l’appel suivant à la méthode de base en tant que première ligne de la structure conditionnelle. Un appel de ce type est généralement nécessaire pour garantir que les contrôles enfants hérités sont créés dans le cas où ils sont restitués entièrement ou partiellement par les CreateChildControls de base, au lieu de l’être par un modèle. Par exemple, le modèle « TextField » de DefaultTemplates.ascx (dans %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\TEMPLATE\ControlTemplates) restitue l’objet TextBox enfant, mais la méthode CreateChildControls ajuste la taille maximale de TextBox sur la taille maximale du champ SPFieldText sous-jacent. Les CreateChildControls de base peuvent également créer des contrôles BaseValidator dynamiques. Toutefois, en règle générale, vous n’avez pas accès au code source de la méthode de base, et c’est donc par expérimentation que vous devez déterminer s’il doit être appelé et, le cas échéant, où il doit être appelé dans votre substitution.
// Make sure inherited child controls are completely rendered. base.CreateChildControls();
' Make sure inherited child controls are completely rendered. MyBase.CreateChildControls()
Ajoutez les lignes ci-après pour associer les contrôles enfants des modèles de rendu aux champs de contrôle enfants déclarés dans votre contrôle de champ personnalisé (ou hérités de son parent). Vous devez le faire maintenant, car l’appel aux CreateChildControls de base associera les contrôles enfants hérités aux modèles de rendu utilisés par le parent de la classe du champ personnalisé, pas aux modèles de rendu personnalisé, ce qui signifie que l’association de base doit être remplacée par une nouvelle.
// Associate child controls in the .ascx file with the // fields allocated by this control. this.ISBNPrefix = (Label)TemplateContainer.FindControl("ISBNPrefix"); this.textBox = (TextBox)TemplateContainer.FindControl("TextField"); this.ISBNValueForDisplay = (Label)TemplateContainer.FindControl("ISBNValueForDisplay");
' Associate child controls in the .ascx file with the ' fields allocated by this control. Me.ISBNPrefix = CType(TemplateContainer.FindControl("ISBNPrefix"), Label) Me.textBox = CType(TemplateContainer.FindControl("TextField"), TextBox) Me.ISBNValueForDisplay = CType(TemplateContainer.FindControl("ISBNValueForDisplay"), Label)
Ajoutez la structure ci-après sous le code d’association du contrôle. Votre champ utilise un modèle de rendu différent (que vous créerez dans une étape ultérieure du présent article) en mode Affichage de celui utilisé dans les modes Création et Édition ; en conséquence, différents contrôles enfants sont initialisés en fonction du mode.
if (this.ControlMode != SPControlMode.Display) { } else // control mode is Display { }// end control mode is Display
If Not Me.ControlMode = SPControlMode.Display Then Else ' control mode is display End If ' end control mode is Display
Ajoutez la structure conditionnelle interne suivante à l’intérieur de la clause « if » (ou « If ») de la structure conditionnelle créée à l’étape précédente. Le code ne doit en rien agir sur une publication, car la réinitialisation sur une publication annulerait toutes les modifications qu’un utilisateur apporterait aux valeurs des contrôles enfants.
if (!this.Page.IsPostBack) { }// end if this is not a postback //Do not reinitialize on a postback.
If Not Me.Page.IsPostBack Then End If ' end if this is not a postback 'Do not reinitialize on a postback.
Dans la structure conditionnelle que vous avez ajoutée à l'étape précédente, ajoutez le conditionnel interne suivant pour initialiser le contrôle enfant TextBox avec une valeur ISBN par défaut lorsque le mode de contrôle est New (Création).
if (this.ControlMode == SPControlMode.New) { textBox.Text = "0-000-00000-0"; } // end assign default value in New mode
If Me.ControlMode = SPControlMode.New Then textBox.Text = "0-000-00000-0" End If ' end assign default value in New mode
Dans le bloc else (ou Else) qui s’exécute quand le contrôle est en mode Affichage, ajoutez le code suivant pour initialiser le champ à sa valeur courante à partir de la base de données de contenu.
// Assign current value from database to the label control ISBNValueForDisplay.Text = (String)this.ItemFieldValue;
' Assign current value from database to the label control ISBNValueForDisplay.Text = CType(Me.ItemFieldValue, String)
Rien ne doit être fait en mode Édition, car la méthode OnLoad initialisera ISBNFieldControl.Value à la valeur de ItemFieldValue qui contient la valeur actuelle du champ dans la base de données de contenu. À ce stade, votre substitution de CreateChildControls doit ressembler à ce qui suit.
protected override void CreateChildControls() { if (this.Field != null) { // Make sure inherited child controls are completely rendered. base.CreateChildControls(); // Associate child controls in the .ascx file with the // fields allocated by this control. this.ISBNPrefix = (Label)TemplateContainer.FindControl("ISBNPrefix"); this.textBox = (TextBox)TemplateContainer.FindControl("TextField"); this.ISBNValueForDisplay = (Label)TemplateContainer.FindControl("ISBNValueForDisplay"); if (this.ControlMode != SPControlMode.Display) { if (!this.Page.IsPostBack) { if (this.ControlMode == SPControlMode.New) { textBox.Text = "0-000-00000-0"; } // end assign default value in New mode }// end if this is not a postback // Do not reinitialize on a postback. }// end if control mode is not Display else // control mode is Display { // Assign current value from database to the label control ISBNValueForDisplay.Text = (String)this.ItemFieldValue; }// end control mode is Display }// end if there is a non-null underlying ISBNField // Do nothing if the ISBNField is null. }
Protected Overrides Sub CreateChildControls() If Me.Field IsNot Then ' Make sure inherited child controls are completely rendered. MyBase.CreateChildControls() ' Associate child controls in the .ascx file with the ' fields allocated by this control. Me.ISBNPrefix = CType(TemplateContainer.FindControl("ISBNPrefix"), Label) Me.textBox = CType(TemplateContainer.FindControl("TextField"), TextBox) Me.ISBNValueForDisplay = CType(TemplateContainer.FindControl("ISBNValueForDisplay"), Label) If Not Me.ControlMode = SPControlMode.Display Then If Not Me.Page.IsPostBack Then If Me.ControlMode = SPControlMode.New Then textBox.Text = "0-000-00000-0" End If ' end assign default value in New mode End If ' end if this is not a postback 'Do not reinitialize on a postback. Else ' control mode is display ' Assign current value from database to the label control ISBNValueForDisplay.Text = CType(Me.ItemFieldValue, String) End If ' end control mode is Display End If ' end if there is a non-null underlying ISBNField ' Do nothing if the ISBNField is null or control mode is Display. End Sub
Ajoutez la substitution suivante de la propriété Value, qui est la valeur du champ dans l’interface utilisateur. Si l’utilisateur final a modifié la valeur sans l’avoir enregistrée, alors la propriété Value n’est pas nécessairement la valeur réelle de l’objet ISBNField sous-jacent (dérivé de SPFieldText) ou de la valeur du champ dans la base de données de contenu. Notez que les accesseurs get et set commencent par appeler EnsureChildControls (qui appellera CreateChildControls si nécessaire). L’appel des EnsureChildControls est obligatoire sauf si (1) vous appelez d’abord la propriété de base et (2) vous savez que les accesseurs set et get de la propriété de base appellent EnsureChildControls. Si vous remplaciez le contrôle enfant TextBox sous-jacent hérité de TextField par un type de contrôle entièrement différent, tel qu’une zone de liste déroulante, alors les accesseurs set et get de votre substitution de la propriété Value devraient définir ce contrôle directement plutôt que d’appeler une propriété de base. Pour s’assurer que le contrôle se charge initialement avec la valeur de l’objet ISBNField sous-jacent, la méthode OnLoad() définit ISBNFieldControl.Value avec la valeur ItemFieldValue qui est la valeur de l’objet ISBNField sous-jacent.
public override object Value { get { EnsureChildControls(); return base.Value; } set { EnsureChildControls(); base.Value = (String)value; // The value of the ISBNPrefix field is hardcoded in the // template, so it is not set here. } }
Public Overrides Property Value() As Object Get EnsureChildControls() Return MyBase.Value End Get Set(ByVal value As Object) EnsureChildControls() MyBase.Value = CType(value, String) ' The value of the ISBNPrefix field is hardcoded in the ' template, so it is not set here. End Set End Property
Création du modèle de rendu de champ
Pour créer les modèles de rendu
Ouvrez le fichier ISBNFieldControl.ascx.
Les directives suivantes se trouvent déjà dans le fichier.
<%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %> <%@ Assembly Name="Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Register Tagprefix="asp" Namespace="System.Web.UI" Assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %> <%@ Import Namespace="Microsoft.SharePoint" %> <%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
Sous ce balisage figure une directive <%@ Control qui fait référence aux fichiers que vous avez supprimés dans une étape antérieure et qui contient d’autres attributs qui ne sont pas utilisés dans ce projet. Remplacez-la par la directive suivante simplifiée.
<%@ Control Language="C#" %>
Sous les directives, ajoutez le balisage ci-après.
<SharePoint:RenderingTemplate ID="ISBNFieldControl" runat="server"> <Template> <asp:Label ID="ISBNPrefix" Text="ISBN" runat="server" /> <asp:TextBox ID="TextField" runat="server" /> </Template> </SharePoint:RenderingTemplate>
Notez les faits suivants à propos de ce balisage :
L’ID du RenderingTemplate doit être identique à la chaîne que vous avez utilisée dans votre substitution de la propriété DefaultTemplateName.
L'attribut Text du contrôle Label est défini ici dans le modèle, car il ne change jamais.
Un élément " " HTML s'insère entre deux contrôles.
La définition de TextBox est identique à celle du RenderingTemplate « TextField » spécifiée dans %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\TEMPLATE\CONTROLTEMPLATES\DefaultTemplates.ascx. Cependant, la définition doit être répétée ici, car votre substitution de DefaultTemplateName pointe vers ce modèle personnalisé, et non vers le modèle « TextField ». Le même ID est utilisé dans le modèle personnalisé, car la méthode CreateChildControls de base (voir ci-dessus) peut faire référence au contrôle par l’intermédiaire de cet ID.
Ajoutez le RenderingTemplate supplémentaire suivant juste sous le premier.
<SharePoint:RenderingTemplate ID="ISBNFieldControlForDisplay" runat="server"> <Template> <asp:Label ID="ISBNValueForDisplay" runat="server" /> </Template> </SharePoint:RenderingTemplate>
Ce RenderingTemplate sera défini comme modèle par défaut en mode d’affichage par la méthode CreateChildControls.
Création de la définition de type de champ
Pour créer la définition de type de champ
Dans Visual Studio, générez le projet. Le projet n’est pas terminé, mais vous devez le générer à ce stade pour créer un GUID et un jeton de clé publique pour l’assembly.
Ouvrez le fichier fldtypes_ISBNField.xml et remplacez son contenu par le balisage suivant.
<?xml version="1.0" encoding="utf-8" ?> <FieldTypes> <FieldType> <Field Name="TypeName">ISBN</Field> <Field Name="ParentType">Text</Field> <Field Name="TypeDisplayName">ISBN</Field> <Field Name="TypeShortDescription">ISBN for a book</Field> <Field Name="UserCreatable">TRUE</Field> <Field Name="ShowOnListCreate">TRUE</Field> <Field Name="ShowOnSurveyCreate">TRUE</Field> <Field Name="ShowOnDocumentLibraryCreate">TRUE</Field> <Field Name="ShowOnColumnTemplateCreate">TRUE</Field> <Field Name="FieldTypeClass">Contoso.SharePoint.ISBNField, $SharePoint.Project.AssemblyFullName$</Field> </FieldType> </FieldTypes>
Ce fichier définit le type de champ personnalisé pour SharePoint Foundation. Pour plus d’informations sur la fonction et la signification de ses éléments, voir Procédure : créer une définition de type de champ personnalisé, Présentation du fichier FldTypes.xml, FieldTypes, élément (Types de champs), FieldType, élément (types de champ) et Field, élément (types de champs). Notez que l’élément <Field Name="FieldTypeClass"> doit tenir entièrement sur une seule ligne.
La valeur de l’élément <Field Name="FieldTypeClass"> est le nom entièrement qualifié de la classe de votre champ personnalisé, suivi d’une virgule et d’un jeton Visual Studio 2010 ($SharePoint.Project.AssemblyFullName$). Lorsque vous compilez le projet, une copie de ce fichier est créée, dans laquelle le jeton est remplacé par le nom complet en quatre parties de l’assembly. C’est cette copie qui est déployée lorsque vous sélectionnez Déployer la solution dans le menu Visual Studio Générer de Visual Studio 2010. Si vous n’utilisez pas Visual Studio 2010, vous devrez compiler le projet à ce stade, même s’il n’est pas terminé, afin de générer un jeton de clé publique. Vous pouvez alors utiliser l’outil décrit dans Procédure : créer un outil pour obtenir le nom complet d'un assembly pour obtenir le nom complet en quatre parties et le coller manuellement à la place du jeton.
Création de la feuille de style XSLT
Pour créer la feuille de style XSLT
Ouvrez le fichier fldtypes_ISBNField.xsl et remplacez le balisage situé sous la balise <?xml version="1.0" encoding="utf-8"?> par celui ci-après.
<xsl:stylesheet xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:d="https://schemas.microsoft.com/sharepoint/dsp" version="1.0" exclude-result-prefixes="xsl msxsl ddwrt" xmlns:ddwrt="https://schemas.microsoft.com/WebParts/v2/DataView/runtime" xmlns:asp="https://schemas.microsoft.com/ASPNET/20" xmlns:__designer="https://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:SharePoint="Microsoft.SharePoint.WebControls" xmlns:ddwrt2="urn:frontpage:internal"> <xsl:template match="FieldRef[@Name = 'ISBN']" mode="Text_body"> <xsl:param name="thisNode" select="." /> <span style="background-color:lightgreen;font-weight:bold"> <xsl:value-of select="$thisNode/@*[name()=current()/@Name]" /> </span> </xsl:template > </xsl:stylesheet>
La feuille de style XSLT restitue le champ sur les affichages de liste. Les cellules de la colonne ISBN des affichages de liste ont un arrière-plan vert clair, la valeur ISBN étant affichée en gras.
L’en-tête de colonne du mode d’affichage de liste est restitué par une autre feuille de style XSLT, fournie dans le fichier intégré fldtypes.xsl de %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\TEMPLATES\LAYOUTS\XSL.
Générer et tester le type de champ personnalisé
Pour générer et tester le type de champ personnalisé
Sélectionnez Déployer dans le menu générer. Cette option régénère automatiquement l’assembly, le déploie sur le GAC, déploie le fichier ascx sur %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\TEMPLATE\ControlTemplates, déploie le fichierfldtypes*.xml sur %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\TEMPLATE\XML, déploie le fichier fldtypes*.xsl sur %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\TEMPLATE\LAYOUTS\XSL, et recycle l’application Web.
Notes
Si votre environnement de développement est une batterie multiserveur, l’étape de déploiement ne se produit pas automatiquement. Déployez la solution, isbn_field_type.wsp, depuis la page Gestion des solutions de l’application Administration centrale ou avec une applet de commande SharePoint Management Shell.
Ouvrez un site Web dans votre application Web SharePoint et créez une liste intitulée Livres.
Ajouter une nouvelle colonne à la liste. Dans la page Créer une colonne, entrez « ISBN » comme nom de colonne.
Cliquez sur la case d'option ISBN pour un livre.
Cliquez sur la case d'option Oui pour rendre le champ obligatoire.
Laissez la case à cocher Ajouter à l'affichage par défaut activée.
Cliquez sur OK.
Ajoutez un élément à la liste.
Sur la page Nouvel élément, vérifiez que le champ est initialement défini avec la valeur par défaut « 0-000-00000-0 » et que, en plus du titre de champ « ISBN », la valeur elle-même est aussi immédiatement précédée par « ISBN » comme défini dans le modèle de rendu des modes Création et Édition.
Entrez des valeurs ISBN non valides pour vérifier quels types d'erreurs vous obtenez lorsque vous essayez d'enregistrer l'élément.
Vérifiez ce qui se passe si vous laissez le champ entièrement vide.
Enfin, entrez 0-262-61108-2 ou une autre valeur que vous savez valide et cliquez sur Enregistrer. (Si vous obtenez des erreurs indiquant un ISBN non valide, vérifiez que vous n’avez pas laissé d’espace vide à la fin de la valeur.)
Vérifiez que la valeur dans l’affichage de liste est en caractères gras sur fond de couleur vert clair.
Cliquez sur le titre de l’élément pour ouvrir la page d’affichage. Confirmez que le champ apparaît avec sa valeur actuelle dans la base de données de contenu. Notez que même si le titre de champ « ISBN » est présent, la valeur elle-même n’est pas immédiatement précédée de « ISBN » comme cela est le cas dans les modes Édition et Création, car ce préfixe n’appartenait pas au modèle de rendu du mode d’affichage.
Cliquez sur Modifier l’élément pour modifier le champ. Confirmez que le champ est initialement défini avec sa valeur courante, pas avec la valeur par défaut, et qu’en plus du titre de champ « ISBN », la valeur elle-même est aussi immédiatement précédée par « ISBN », tel que défini dans le modèle de rendu des modes Édition et Création.
Modifiez le champ en y indiquant des valeurs non valides et vérifiez que des erreurs de validation apparaissent en mode Édition exactement comme en mode Création.
Différences de rendu des champs entre les périphériques mobiles et les ordinateurs
Dans SharePoint Foundation, le rendu de champ avec contrôles de rendu de champ personnalisé pour les périphériques mobiles est similaire au rendu de champ avec contrôles de rendu de champ personnalisé pour les ordinateurs. Mais gardez ces différences présentes à l’esprit :
Les pages mobiles constituent un ensemble de pages totalement distinct des pages principales d'un site SharePoint Foundation (qui sont conçues pour les navigateurs d'ordinateur) et font référence à un ensemble différent d'objets RenderingTemplate.
Les objets RenderingTemplate mobiles sont déclarés dans MobileDefaultTemplates.ascx et GbwMobileDefaultTemplates.ascx, pas dans DefaultTemplates.ascx.
Les contrôles de rendu de champ mobiles possèdent leur propre espace de noms, Microsoft.SharePoint.MobileControls et dérivent de classes de l'espace de noms System.Web.UI.MobileControls ASP.NET (plutôt que de l'espace de noms System.Web.UI.WebControls).
Pour les contrôles de rendu de champ mobiles, la hiérarchie d'héritage est un peu différente de celle des contrôles de rendu de champ normaux. Par exemple, les fonctions de TemplateBasedControl et de FormComponent dans le rendu de champ normal sont combinées dans la classe SPMobileComponent.
Les contrôles de rendu de champ personnalisés que vous créez pour des contextes mobiles reposent plus sur la méthode CreateChildControls du contrôle pour restituer un champ, et moins sur le modèle de rendu, que dans le cas des contrôles de rendu de champ personnalisés que vous créez pour les navigateurs d'ordinateur. En outre, en développant des contrôles de rendu mobiles personnalisés, vous ne substituerez pas souvent la méthode CreateChildControls à proprement parler. À la place, vos contrôles de rendu mobiles personnalisés substitueront généralement une ou plusieurs des quatre méthodes qui sont appelées par la méthode CreateChildControls :
Voir aussi
Référence
FieldTypes, élément (Types de champs)
FieldType, élément (types de champ)
Field, élément (types de champs)
RenderPattern, élément (Types de champs)
Label
OnLoad()
RegularExpressions
TextBox
Concepts
Procédure : créer une classe de champ personnalisé
Procédure : créer une définition de type de champ personnalisé
Déploiement de types de champs personnalisés
Validation des données du champ personnalisé
Procédure : créer un contrôle de rendu de champ
Procédure : créer des modèles de rendu de champ