Partager via


Procédure : créer une recherche à plusieurs colonnes

Dernière modification : mercredi 1 décembre 2010

S’applique à : SharePoint Foundation 2010

Dans Microsoft SharePoint Foundation, une colonne de recherche désigne une colonne configurée pour afficher une valeur d’une colonne d’une autre liste. Quand les utilisateurs créent un nouvel élément, ils n’entrent pas la valeur de la colonne de recherche, mais sélectionnent une valeur dans une liste déroulante de valeurs de la colonne de l’autre liste. Dans SharePoint Foundation 2010, il est possible de créer une colonne de recherche à plusieurs colonnes où une colonne de recherche principale permet de sélectionner un élément de la liste cible et où une ou plusieurs colonnes de recherche secondaires affichent les valeurs des autres colonnes du même élément de liste.

La cible d’une colonne de recherche peut être l’un des types de champs suivants : Counter, DateTime, Number, Text. Pour plus d’informations sur ces types de champs, voir l’énumération SPFieldType. En outre, le type de champ Calculated peut être une cible si la sortie contient du texte. Pour plus d’informations, voir la propriété OutputType de la classe SPFieldCalculated. Le type de champ Computed peut être une cible si les recherches sont activées pour le champ. Pour plus d’informations, voir la propriété EnableLookup de la classe SPFieldComputed.

La façon de créer une recherche à plusieurs colonnes varie selon que vous voulez définir les colonnes d’une nouvelle liste ou ajouter des colonnes à une liste existante. Dans les deux cas, il est fort vraisemblable que vous créerez les colonnes dans le contexte d’une fonctionnalité. Pour plus d’informations sur l’implémentation d’une fonctionnalité, voir Utilisation des fonctionnalités.

Création de colonnes de recherche sur une nouvelle liste

Lorsque vous créez les colonnes de recherche sur une liste que vous créez aussi dans le cadre de la même fonctionnalité, la solution la plus simple pour définir les colonnes et la liste consiste à écrire les déclarations XML. Les Outils de développement SharePoint dans Microsoft Visual Studio 2010 incluent plusieurs modèles qui effectuent certaines tâches à votre place. Les modèles créent aussi un package de solution pour la fonctionnalité, le déploient automatiquement quand vous appuyez sur la touche F5 et retirent la solution lorsque vous cessez le débogage. Il est ainsi extrêmement aisé de conduire un processus de développement itératif.

Vous pouvez définir les colonnes de recherche principales et secondaires dans le cadre de la définition d’une nouvelle liste (autrement dit, dans le cadre du schéma de liste). Cependant, la meilleure pratique consiste à créer des colonnes de site, à les inclure dans un type de contenu de site et à utiliser le type de contenu comme base d’une nouvelle liste. Cette approche encourage la réutilisabilité, parce qu’elle permet d’utiliser les colonnes d’autres listes. Elle permet aussi de conserver et de mettre à jour les définitions des colonnes indépendamment de la définition des listes.

Avant de commencer, vous devez recueillir quelques informations sur la liste qui sera la cible des colonnes de recherche. D’abord, vous devez savoir identifier la liste cible. Une colonne de recherche, et tel est le cas pour toute colonne, est définie par un élément Field d’un fichier XML. La liste cible d’une colonne de recherche est identifiée par la valeur de l’attribut List de l’élément Field. La valeur d’attribut peut être un ID de liste (un GUID) ou une URL relative de site Web. La seconde option, une URL relative de site Web, ne fonctionne que lorsque la liste cible n’existe pas encore. Dans ce cas, vous devez créer la liste cible dans la même fonctionnalité que celle qui crée la colonne de recherche.

Si la liste cible existe déjà, vous pouvez obtenir son ID en écrivant une application console simple qui obtient une référence à l’objet SPList, lequel représente la liste et affiche la valeur de la propriété ID sur la console. La valeur souhaitée est renvoyée par la méthode ToString("B") de la classe System.Guid.

using (SPSite site = new SPSite("https://localhost"))
{
    using (SPWeb web = site.RootWeb)
    {
        SPList list = web.Lists.TryGetList("Contoso Cutomers");
        if (list != null)
            Console.WriteLine(list.ID.ToString("B"));
    }
}

Vous pouvez aussi obtenir l’ID à l’aide de Microsoft SharePoint Designer 2010. Ouvrez le site Web, sélectionnez Listes et bibliothèques dans le volet de navigation, cliquez avec le bouton droit sur le nom de la liste et choisissez Paramètres de la liste. Recherchez ID de liste sous Informations sur la liste. Copiez la totalité du GUID, accolades incluses.

En outre, vous aurez besoin du nom interne de chaque champ de la liste cible vers lequel pointe l’un de vos champs de recherche. Le nom interne est la valeur de l’attribut Name de l’élément Field si vous regardez la définition du champ, ou la valeur renvoyée par la propriété InternalName de l’objet SPField si vous recueillez les informations en écrivant le code.

ConseilConseil

Vous pouvez trouver les noms internes des colonnes intégrées au sein de la documentation de la classe SPBuiltInFieldId. Le nom de chaque champ de la classe est le nom interne d’une colonne intégrée. Par exemple, le nom interne du champ Créé par est Created_x0020_By.

La procédure générale de création d’une recherche à plusieurs colonnes sur une nouvelle liste se compose des tâches suivantes :

  1. Définir les colonnes de recherche comme colonnes de site.

  2. Définir un type de contenu qui utilise les colonnes de recherche.

  3. Définir une liste et une instance de liste à partir du nouveau type de contenu.

  4. Déployer, activer et tester la fonctionnalité.

Pour définir les colonnes de recherche comme colonnes de site

  1. Dans Visual Studio 2010, créez un projet à l’aide du modèle Projet SharePoint vide pour SharePoint 2010.

  2. Dans l’Assistant Personnalisation de SharePoint, sélectionnez Déployer en tant que solution bac à sable (sandbox). Cliquez sur Terminer.

  3. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le dossier Fonctionnalités et sélectionnez Ajouter une fonctionnalité.

    Le concepteur de fonctionnalités s’affiche. Vous pouvez modifier le titre et la description, et sélectionner une étendue pour la fonctionnalité. Web ou Site est une étendue appropriée pour cette application. Pour plus d’informations, voir Scope, paramètre de l'élément Feature.

  4. (Facultatif) Créez une liste cible pour les recherches.

    Pour créer la liste cible à partir d’une définition de liste personnalisée, suivez les procédures décrites dans Procédure : créer une définition de liste personnalisée. Pour créer la liste cible à partir d’une définition de liste existante, utilisez la procédure suivante :

    1. Dans l’Explorateur de solutions, sélectionnez le projet, puis, dans le menu Projet, sélectionnez Ajouter un nouvel élément.

    2. Dans la boîte de dialogue Ajouter un nouvel élément, choisissez le modèle Instance de liste et tapez un nom pour la liste. Cliquez sur Ajouter.

    3. Suivez les invites de l’Assistant Personnalisation de SharePoint.

      L’Assistant vous demande de choisir un modèle de liste et de spécifier une URL pour la liste.

  5. Créez la définition de champ pour la colonne de recherche principale.

    1. Dans l’Explorateur de solutions, cliquez sur le projet, puis, dans le menu Projet, sélectionnez Ajouter un nouvel élément.

    2. Dans la boîte de dialogue Ajouter un nouvel élément, choisissez le modèle Élément vide, attribuez un nom à l’élément (par exemple, « SiteColumns ») et cliquez sur Ajouter.

      Visual Studio utilise le nom que vous entrez comme nom d’un dossier qu’il ajoute au projet. À l’intérieur du dossier, Visual Studio crée un fichier intitulé Elements.xml.

    3. Dans Elements.xml, insérez le code XML suivant dans l’élément Elements :

      <!-- Primary lookup column -->
      <Field Type="Lookup" Name="" ID="" List="" ShowField="" DisplayName="" Required="" Group="" />
      
    4. Tapez la valeur de l’attribut Name.

      Il s’agit du nom interne du champ. Le nom doit être unique au sein de la collection renvoyée par la propriété AvailableFields du site Web où le champ sera créé. SharePoint Foundation modifie la valeur si nécessaire pour garantir son unicité.

    5. Dans le menu Outils de Visual Studio, choisissez Créer un GUID. Dans la boîte de dialogue Créer un GUID, sélectionnez Format du Registre, cliquez sur Copier, puis sur Quitter.

      Un nouveau GUID est copié dans le Presse-papiers.

    6. Spécifiez une valeur pour l’attribut ID en collant le nouveau GUID (accolades incluses) entre les guillemets.

    7. Spécifiez une valeur pour l’attribut List.

      L’attribut List identifie la liste cible de la colonne de recherche. Si la liste existe déjà, la valeur est l’ID de liste, GUID avec accolades incluses.

      Si la liste cible n’existe pas encore, vous pouvez utiliser une URL relative de site Web (telle que Lists/Contoso Customers) comme valeur de l’attribut List. Cependant, vous devez créer la liste dans le cadre de la même fonctionnalité que celle qui crée la colonne de recherche. (Voir l’étape 4.) Utilisez la valeur de l’attribut Url sur l’élément ListInstance qui crée la liste cible.

    8. Spécifiez une valeur pour l’attribut ShowField.

      La valeur de l’attribut ShowField est le nom interne du champ cible de la liste identifiée par l’attribut List.

    9. Spécifiez une valeur pour l’attribut DisplayName.

      Il s’agit du nom affiché pour la colonne dans les affichages de liste et sur les formulaires. La longueur maximale est 255 caractères. La valeur peut être une référence à une ressource localisée au format $Resources:String. Pour plus d’informations, voir Localisation de solutions SharePoint.

    10. Définissez l’attribut Required avec la valeur true ou false.

      Spécifiez true si les utilisateurs qui complètent le formulaire New ou Edit d’un élément de liste doivent obligatoirement sélectionner une valeur pour le champ. Spécifiez false si le champ peut être vide.

    11. (Facultatif). Spécifiez une valeur pour l’attribut Group.

      L’attribut Group spécifie le nom du groupe dans lequel placer la colonne quand elle est présente dans la galerie Site Columns. Si un groupe avec ce nom n’existe pas encore, il est créé. La définition d’un groupe pour les colonnes que vous créez facilite leur maintenance.

  6. Créez la définition de champ d’une colonne de recherche secondaire.

    1. Dans Elements.xml, insérez le code XML suivant dans l’élément Elements :

      <!-- Secondary lookup column -->
      <Field Type="Lookup" FieldRef="" Name="" ID="" List="" ShowField="" DisplayName="" Required="" Group="" ReadOnly="TRUE" />
      
    2. Spécifiez une valeur pour l’attribut FieldRef.

      Cet attribut référence la définition de champ de la colonne de recherche principale. Utilisez la valeur de l’attribut ID de la recherche principale, mais sans les accolades.

    3. Spécifiez les valeurs des attributs restants comme à l’étape 5.

  7. Créez les définitions de champ de chacune des colonnes de recherche secondaires restantes de votre fonctionnalité en répétant l’étape 6 autant de fois que nécessaire.

À ce stade, vos définitions de champ doivent être similaires à l’exemple suivant, lequel définit une recherche à plusieurs colonnes sur la liste Contoso Customers.

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="https://schemas.microsoft.com/sharepoint/">
  <!-- Primary lookup column: CustIDLookup -->
  <Field Type="Lookup" 
         Name="CustIDLookup" 
         ID="{2A670022-84AF-4C51-84F7-8E1B6025F104}" 
         List="Lists/Contoso Customers" 
         ShowField="ID" 
         DisplayName="Customer ID" 
         Required="true" 
         Group="Contoso Columns"/>
  <!-- Secondary lookup column: CustFirstNameLookup -->
  <Field Type="Lookup" 
         FieldRef="2A670022-84AF-4C51-84F7-8E1B6025F104" 
         Name="CustFirstNameLookup" 
         ID="{F0AF2CA5-EA71-46F7-9536-036539BA8C5C}" 
         List="Lists/Contoso Customers" 
         ShowField="FirstName" 
         DisplayName="First Name" 
         Required="false" 
         Group="Contoso Columns" 
         ReadOnly="TRUE" />
  <!-- Secondary lookup column: CustLastNameLookup -->
  <Field Type="Lookup" 
         FieldRef="2A670022-84AF-4C51-84F7-8E1B6025F104" 
         Name="CustLastNameLookup" 
         ID="{1D7973CE-49CD-46BD-9355-81014246578D}" 
         List="Lists/Contoso Customers" 
         ShowField="Title" 
         DisplayName="Last Name" 
         Required="false" 
         Group="Contoso Columns" 
         ReadOnly="TRUE" />
  <!-- Secondary lookup column: CustPhoneLookup -->
  <Field Type="Lookup" 
         FieldRef="2A670022-84AF-4C51-84F7-8E1B6025F104" 
         Name="CustPhoneLookup" 
         ID="{0F51E81B-2001-4A52-B33A-0F401814118B}" 
         List="Lists/Contoso Customers" 
         ShowField="HomePhone" 
         DisplayName="Phone" 
         Required="false" 
         Group="Contoso Columns" 
         ReadOnly="TRUE" />
</Elements>

Pour définir un type de contenu de site

  1. Dans l’Explorateur de solutions, cliquez sur le projet, puis, dans le menu Projet, sélectionnez Ajouter un nouvel élément.

  2. Dans la boîte de dialogue Ajouter un nouvel élément, choisissez le modèle Type de contenu, attribuez un nom au type de contenu (par exemple, « CustomerOrder »), puis cliquez sur Ajouter.

    La boîte de dialogue Choisir les paramètres de type de contenu s’affiche.

  3. Sélectionnez un type de contenu de base à partir duquel hériter. Cliquez sur Terminer.

    Visual Studio utilise le nom que vous avez entré comme nom de dossier à ajouter au projet. À l’intérieur du dossier se trouve un fichier nommé Elements.xml. C’est à cet emplacement que vous définissez le type de contenu.

  4. Ouvrez le fichier Elements.xml dans l’éditeur.

    Notes

    Vous avez ouvert le fichier correct s’il contient un élément Elements contenant lui-même un élément ContentType qui contient un élément FieldRef.

  5. (Facultatif) Visual Studio définit l’attribut Inherits de l’élément ContentType avec la valeur TRUE. Si vous prévoyez de remplacer les caractéristiques de champs hérités (en modifiant le nom complet, par exemple), définissez l’attribut Inherits avec la valeur FALSE.

  6. Référencez la colonne de recherche principale en collant le code XML suivant à l’intérieur de l’élément FieldRefs :

    <FieldRef ID="" Name="" DisplayName="" Required=""/>
    
  7. Définissez les attributs ID et Name avec les mêmes valeurs que celles des attributs de l’élément Field qui définit la colonne de recherche principale.

    Comme l’attribut ID est sensible à la casse, veillez à copier exactement la même valeur que celle que contient l’élément Field. Assurez-vous d’inclure les accolades.

  8. Spécifiez les valeurs des attributs DisplayName et Required.

  9. Répétez les étapes 6 à 8 pour chaque colonne de recherche secondaire.

  10. Répétez les étapes 6 à 8 pour chaque colonne héritée dont vous voulez modifier les caractéristiques.

    Pour plus d’informations, voir Procédure : référencer une colonne dans un type de contenu.

La définition de votre type de contenu doit désormais ressembler à l’exemple suivant.

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="https://schemas.microsoft.com/sharepoint/">
  <!-- Parent ContentType: Item (0x01) -->
  <ContentType ID="0x0100b4160be88d9a4d669f690459bdcf43ff"
               Name="Contoso - Order"
               Group="Contoso Content Types"
               Description="Represents a customer order"
               Inherits="FALSE"
               Version="0">
    <FieldRefs>
      <FieldRef ID="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}" Name="Title" DisplayName="Description" Required="TRUE"/>
      <FieldRef ID="{bc91a437-52e7-49e1-8c4e-4698904b2b6d}" Name="LinkTitleNoMenu" DisplayName="Description" ReadOnly="TRUE" />
      <FieldRef ID="{82642ec8-ef9b-478f-acf9-31f7d45fbc31}" Name="LinkTitle" DisplayName="Description" ReadOnly="TRUE"/>
      <FieldRef ID="{2A670022-84AF-4C51-84F7-8E1B6025F104}" Name="CustIDLookup" DisplayName="Customer ID" Required="TRUE"/>
      <FieldRef ID="{F0AF2CA5-EA71-46F7-9536-036539BA8C5C}" Name="CustFirstNameLookup" DisplayName="First Name" Required="FALSE"/>
      <FieldRef ID="{1D7973CE-49CD-46BD-9355-81014246578D}" Name="CustLastNameLookup" DisplayName="Last Name" Required="FALSE"/>
      <FieldRef ID="{0F51E81B-2001-4A52-B33A-0F401814118B}" Name="CustPhoneLookup" DisplayName="Phone" Required="FALSE"/>
    </FieldRefs>
  </ContentType>
</Elements>

Pour définir une liste et une instance de liste

  1. Dans l’Explorateur de solutions, cliquez sur le projet, puis, dans le menu Projet, sélectionnez Ajouter un nouvel élément.

  2. Dans la boîte de dialogue Ajouter un nouvel élément, choisissez le modèle Définition de liste du type de contenu, attribuez un nom à la liste (par exemple, « OrdersListDefinition ») et cliquez sur Ajouter.

    La boîte de dialogue Choisir les paramètres de définition de liste s’affiche.

  3. Sélectionnez le type de contenu qui inclut les colonnes de recherche, activez la case à cocher Ajouter une instance de liste pour cette définition de la liste et cliquez sur Terminer.

    Visual Studio utilise le nom que vous avez entré comme nom de dossier à ajouter au projet. À l’intérieur du dossier se trouvent un fichier Elements.xml qui contient un élément ListTemplate, un fichier Schema.xml qui contient un élément List et un dossier ListInstance1 qui contient un autre fichier Elements.xml avec un élément ListInstance.

  4. Ouvrez le fichier Schema.xml.

    Notez que l’élément ContentTypes contient une copie de la définition du type de contenu et que l’élément Fields contient les copies des définitions de champ de vos colonnes de recherche.

    Faites défiler l’élément Views vers le bas. Notez que deux affichages sont définis, mais qu’aucun des deux ne contient les éléments FieldRef qui référencent vos colonnes de recherche.

  5. Copiez les éléments FieldRef des colonnes que vous voulez voir apparaître dans un affichage de liste et collez-les à l’intérieur de l’élément ViewFields de la définition de l’affichage.

    Seuls les attributs ID et Name sont obligatoires pour les éléments FieldRef à l’intérieur d’un élément ViewFields.

L’élément Views de votre fichier Schema.xml doit être similaire à l’exemple suivant.

<Views>
  <View BaseViewID="0" Type="HTML" MobileView="TRUE" TabularView="FALSE">
    <Toolbar Type="Standard" />
    <XslLink Default="TRUE">main.xsl</XslLink>
    <RowLimit Paged="TRUE">30</RowLimit>
    <ViewFields>
      <FieldRef Name="LinkTitleNoMenu"></FieldRef>
      <FieldRef ID="{2A670022-84AF-4C51-84F7-8E1B6025F104}" Name="CustIDLookup" />
      <FieldRef ID="{F0AF2CA5-EA71-46F7-9536-036539BA8C5C}" Name="CustFirstNameLookup" />
      <FieldRef ID="{1D7973CE-49CD-46BD-9355-81014246578D}" Name="CustLastNameLookup"  />
      <FieldRef ID="{0F51E81B-2001-4A52-B33A-0F401814118B}" Name="CustPhoneLookup" />
    </ViewFields>
    <Query>
      <OrderBy>
        <FieldRef Name="Modified" Ascending="FALSE">
        </FieldRef>
      </OrderBy>
    </Query>
    <ParameterBindings>
      <ParameterBinding Name="AddNewAnnouncement" Location="Resource(wss,addnewitem)" />
      <ParameterBinding Name="NoAnnouncements" Location="Resource(wss,noXinviewofY_LIST)" />
      <ParameterBinding Name="NoAnnouncementsHowTo" Location="Resource(wss,noXinviewofY_ONET_HOME)" />
    </ParameterBindings>
  </View>
  <View BaseViewID="1" Type="HTML" WebPartZoneID="Main" DisplayName="$Resources:core,objectiv_schema_mwsidcamlidC24;" DefaultView="TRUE" MobileView="TRUE" MobileDefaultView="TRUE" SetupPath="pages\viewpage.aspx" ImageUrl="/_layouts/images/generic.png" Url="AllItems.aspx">
    <Toolbar Type="Standard" />
    <XslLink Default="TRUE">main.xsl</XslLink>
    <RowLimit Paged="TRUE">30</RowLimit>
    <ViewFields>
      <FieldRef Name="Attachments">
      </FieldRef>
      <FieldRef Name="LinkTitle">
      </FieldRef>
      <FieldRef ID="{2A670022-84AF-4C51-84F7-8E1B6025F104}" Name="CustIDLookup" />
      <FieldRef ID="{F0AF2CA5-EA71-46F7-9536-036539BA8C5C}" Name="CustFirstNameLookup" />
      <FieldRef ID="{1D7973CE-49CD-46BD-9355-81014246578D}" Name="CustLastNameLookup"  />
      <FieldRef ID="{0F51E81B-2001-4A52-B33A-0F401814118B}" Name="CustPhoneLookup" />
    </ViewFields>
    <Query>
      <OrderBy>
        <FieldRef Name="ID">
        </FieldRef>
      </OrderBy>
    </Query>
    <ParameterBindings>
      <ParameterBinding Name="NoAnnouncements" Location="Resource(wss,noXinviewofY_LIST)" />
      <ParameterBinding Name="NoAnnouncementsHowTo" Location="Resource(wss,noXinviewofY_DEFAULT)" />
    </ParameterBindings>
  </View>
</Views>

Pour déployer, activer et tester la fonctionnalité

  1. Appuyez sur F5 pour déployer la solution et activer la fonctionnalité.

  2. Dans le menu Actions du site, choisissez Paramètres du site.

  3. Sous Galeries, cliquez sur Colonnes de site. Vérifiez que la colonne de recherche principale existe dans la collection des colonnes du site.

  4. Cliquez sur le nom de la colonne de recherche principale. Dans la page Modifier la colonne de site, sous Ajouter une colonne pour afficher chacun des champs supplémentaires suivants, vérifiez que les noms des colonnes de recherche secondaires sont cochés.

  5. Retournez à la page Paramètres du site. Sous Galeries, cliquez sur Types de contenu de site.

  6. Cliquez sur le nom de votre type de contenu. Dans la page Informations sur les types de contenu de site, sous Colonnes, vérifiez que la colonne de recherche principale est présente.

  7. Dans le volet de navigation gauche, cliquez sur le nom de votre liste.

  8. Dans le Ruban, cliquez sur Liste, puis sur Paramètres de la liste.

  9. Dans la page Paramètres de la liste, sous Colonnes, vérifiez que les colonnes de recherche principales et secondaires sont présentes.

  10. Revenez à l’affichage de la liste. Essayez d’ajouter un nouvel élément à la liste. (Il se peut que vous ayez besoin au préalable d’ajouter des éléments à la liste cible.)

  11. Une fois que vous avez terminé, fermez le navigateur pour arrêter le débogage.

    Visual Studio désactive la fonctionnalité et retire la solution.

Étapes suivantes

Lorsqu’elle est désactivée, une fonctionnalité complète doit supprimer les objets qu’elle a créés. Visual Studio tente d’effectuer la plus grande part possible de cette tâche, afin de faciliter le processus de développement itératif, mais dans un environnement de production, la fonctionnalité est censée procéder elle-même à cette suppression. À cette fin, il vous appartiendra d’écrire le code correspondant.

L’emplacement approprié du code de nettoyage se trouve dans la méthode FeatureDeactivating d’une sous-classe de la classe SPFeatureReceiver. Cependant, votre comportement ici-même dépend dans une certaine mesure de la stratégie interne. Par exemple, il est probable que vous ne souhaiterez pas supprimer les listes si elles contiennent des données précieuses. Dans ce cas, vous devrez trouver un moyen de stocker les données afin que les utilisateurs puissent les récupérer. En dehors de ce type de considération, vous devez garder présentes à l’esprit les instructions générales suivantes lorsque vous écrivez le code de la méthode FeatureDeactivating :

  • Supprimez les types de contenu de liste avant de supprimer le type de contenu de site dont ils sont dérivés.

    Vous pouvez appeler la méthode statique SPContentTypeUsage.GetUsages pour obtenir des informations sur l’emplacement où un type de contenu est utilisé. Pour obtenir un exemple, voir la méthode Delete de la classe SPContentTypeCollection.

  • Supprimez les types de contenu de site avant de supprimer les colonnes de site qui les référencent.

  • Supprimez toutes les colonnes de recherche secondaires avant de supprimer la colonne de recherche principale dont elles dépendent.

    Pour obtenir un exemple, voir l’implémentation de la méthode FeatureDeactivating à la fin de la section suivante, « Ajout de colonnes de recherche à une liste existante ».

  • Enregistrez les exceptions et les défaillances afin qu’un administrateur puisse résoudre les problèmes si nécessaire.

Ajout de colonnes de recherche à une liste existante

Vous pouvez ajouter des colonnes de recherche à une liste déjà existante en écrivant le code serveur qui utilise le modèle objet SharePoint Foundation. La meilleure solution consiste à créer une fonctionnalité et à écrire le code dans un récepteur d’événements de la fonctionnalité. Votre code crée les colonnes de recherche quand la fonctionnalité est activée.

Notes

La procédure suivante présume que la liste qui est la cible des colonnes de recherche existe dans le même site Web que la liste contenant les colonnes de recherche. Les recherches Web croisées sont possibles. Pour plus d’informations, voir la propriété LookupWebId.

Pour ajouter une recherche à plusieurs colonnes à une liste existante

  1. Dans Visual Studio 2010, créez un projet à l’aide du modèle Projet SharePoint vide pour SharePoint 2010.

  2. Dans l’Assistant Personnalisation de SharePoint, sélectionnez Déployer en tant que solution bac à sable (sandbox). Cliquez sur Terminer.

  3. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le dossier Fonctionnalités et sélectionnez Ajouter une fonctionnalité.

    Le concepteur de fonctionnalités s’affiche. Vous pouvez modifier le titre et la description, et sélectionner une étendue pour la fonctionnalité. Web ou Site est une étendue appropriée pour cette application. Pour plus d’informations, voir Scope, paramètre de l'élément Feature.

  4. Cliquez avec le bouton droit sur le nom de la fonctionnalité (par exemple, Fonctionnalité1) et sélectionnez Ajouter un récepteur d’événements.

    Visual Studio crée une sous-classe de la classe SPFeatureReceiver.

  5. Annulez les marques de commentaire de la méthode FeatureActivated.

  6. Dans la méthode FeatureActivated, écrivez le code pour obtenir le site Web courant (si l’étendue de la fonctionnalité est Web) ou le site Web racine de la collection de sites (si l’étendue est Site).

    À cette fin, accédez à la propriété Feature de l’objet SPFeatureReceiverProperties transmis à la méthode comme paramètre de properties. La propriété Feature renvoie un objet SPFeature. La propriété Parent de cet objet renvoie un objet SPWeb de type Object si la portée de l’étendue est Web ou à un objet de type SPSite si l’étendue est Site.

    L’extrait de code suivant illustre la technique utilisée.

    SPWeb web = properties.Feature.Parent as SPWeb;
    if (web == null)
    {
        SPSite site = properties.Feature.Parent as SPSite;
        if (site != null)
            web = site.RootWeb;
    }
    
    Dim web As SPWeb = TryCast(properties.Feature.Parent, SPWeb)
    If web Is Nothing Then
        Dim site As SPSite = TryCast(properties.Feature.Parent, SPSite)
        If site IsNot Nothing Then
            web = site.RootWeb
        End If
    End
    
  7. Instanciez deux objets SPList, l’un pour la liste qui recevra les colonnes de recherche, l’autre pour la liste qui est la cible des colonnes de recherche.

    Par exemple, l’extrait de code suivant crée les objets qui correspondent aux listes Contoso Orders et Contoso Customers.

    SPList customers = web.Lists.TryGetList("Contoso Customers");
    SPList orders = web.Lists.TryGetList("Contoso Orders");
    
    Dim customers As SPList = web.Lists.TryGetList("Contoso Customers")
    Dim orders As SPList = web.Lists.TryGetList("Contoso Orders")
    
  8. Instanciez les objets SPField pour représenter les colonnes qui seront les cibles des colonnes de recherche.

    Par exemple, le code suivant instancie les objets pour représenter les quatre colonnes de la liste Contoso Customers qui seront les cibles des colonnes de recherche de la liste Contoso Orders.

    SPField custID, custLName, custFName, custPhone;
    try
    {
        custID = customers.Fields.GetField("ID");
        custFName = customers.Fields.GetField("First Name");
        custLName = customers.Fields.GetField("Last Name");
        custPhone = customers.Fields.GetField("Contact Phone");
    }
    catch (ArgumentException ex)
    {
    
        // One of the fields was not found on the Customers list.
        System.Diagnostics.Trace.WriteLine(logEntry + ex.Message);
        return;
    }
    
    Dim custID, custLName, custFName, custPhone As SPField
    Try
        custID = customers.Fields.GetField("ID")
        custFName = customers.Fields.GetField("First Name")
        custLName = customers.Fields.GetField("Last Name")
        custPhone = customers.Fields.GetField("Contact Phone")
    Catch ex As ArgumentException
    
        ' One of the fields was not found on the Customers list.
        System.Diagnostics.Trace.WriteLine(logEntry + ex.Message)
        Return
    End Try
    
  9. Créez la colonne de recherche principale en appelant la méthode AddLookup de l’objet SPFieldCollection renvoyé par la propriété Fields de la liste qui recevra les colonnes de recherche.

    La méthode AddLookup possède trois paramètres :

    • displayName - Chaîne contenant le nom complet de la colonne de recherche.

    • lookupListId - GUID correspondant à l’ID de la liste cible.

    • bRequired --- Valeur Boolean qui indique si les utilisateurs doivent sélectionner une valeur pour la colonne de recherche sur les formulaires New et Edit.

    La méthode renvoie une chaîne qui contient le nom interne de la colonne de recherche. Vous pouvez récupérer un objet qui représente la nouvelle colonne en transmettant le nom interne à la méthode GetFieldByInternalName.

    Par exemple, le code suivant crée une colonne de recherche sur la liste Contoso Orders qui possède Customer ID comme nom complet et affiche la liste Contoso Customers.

    string strPrimary = orders.Fields.AddLookup("Customer ID", customers.ID, true);
    
    Dim strPrimary As String = orders.Fields.AddLookup("Customer ID", customers.ID, True)
    
  10. Définissez la propriété LookupField de la colonne de recherche principale de telle sorte qu’elle pointe sur une colonne de la liste cible.

    Vous pouvez récupérer un objet SPField qui représente la nouvelle colonne de recherche principale en passant le nom interne renvoyé par la méthode AddLookup comme argument de GetFieldByInternalName(String). Puis, effectuez un cast sur l’objet SPField comme type SPFieldLookup avant d’accéder à la propriété LookupField. Cette propriété accepte une chaîne contenant le nom interne du champ cible.

    Le code suivant définit la propriété LookupField de la colonne créée dans le cadre de l’exemple de l’étape précédente.

    SPFieldLookup primary = orders.Fields.GetFieldByInternalName(strPrimary) as SPFieldLookup;
    primary.LookupField = custID.InternalName;
    primary.Update();
    
    Dim primary As SPFieldLookup = TryCast(orders.Fields.GetFieldByInternalName(strPrimary), SPFieldLookup)
    primary.LookupField = custID.InternalName
    primary.Update()
    
  11. Créez les colonnes de recherche secondaire en appelant la méthode AddDependentLookup de la collection de champs appartenant à la liste qui contiendra les colonnes de recherche.

    La méthode AddDependentLookup possède deux paramètres :

    • displayName - Chaîne contenant le nom complet de la colonne de recherche.

    • primaryLookupFieldId - GUID contenant l’ID de la colonne de recherche principale.

    Comme la méthode AddLookup, la méthode AddDependentLookup renvoie une chaîne qui contient le nom interne de la nouvelle colonne.

    La ligne de code suivante crée une colonne Last Name qui dépend de la colonne de recherche principale créée dans un exemple précédent.

    string strLName = orders.Fields.AddDependentLookup("Last Name", primary.Id);
    
    Dim strLName As String = orders.Fields.AddDependentLookup("Last Name", primary.Id)
    
  12. Définissez la propriété LookupField de la nouvelle colonne de recherche secondaire en suivant la même procédure qu’à l’étape 10.

  13. Répétez les étapes 10 à 11 pour chaque colonne de recherche secondaire que vous souhaitez ajouter.

  14. (Facultatif.) Ajoutez une ou plusieurs colonnes de recherche aux affichages de liste en appelant la méthode Add de l’objet SPViewFieldCollection retourné par chaque propriété ViewFields de l’affichage.

Exemple

L’exemple suivant contient la totalité du code d’une sous-classe de la classe SPFeatureReceiver qui crée et supprime les colonnes de recherche de la liste Contoso Orders. Le code de la méthode FeatureActivated crée une colonne de recherche principale nommée Customer ID qui recherche la valeur de la colonne ID de la liste Contoso Customers. Ensuite, le code crée les colonnes de recherche secondaires pour First Name, Last Name et Phone, et ajoute les colonnes secondaires à l’affichage par défaut de la liste Contoso Orders.

L’exemple inclut également le code de la méthode FeatureDeactivating, qui supprime l’ensemble des colonnes de recherche créées dans la méthode FeatureActivated. Notez que vous devez supprimer toutes les colonnes de recherche secondaires avant de supprimer la colonne de recherche principale dont elles dépendent.

using System;
using System.Runtime.InteropServices;
using Microsoft.SharePoint;

namespace Contoso.Orders.Features.CustomerLookups
{
    [Guid("49e72c4b-cfcb-4665-9c2a-fdadf0a3b018")]
    public class CustomerLookupsEventReceiver : SPFeatureReceiver
    {

        // Define static field names.
        const string STATIC_CUST_ID = "CustID";
        const string STATIC_CUST_FNAME = "CustFName";
        const string STATIC_CUST_LNAME = "CustLName";
        const string STATIC_CUST_PHONE = "CustPhone";

        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            string logEntry = properties.Definition.DisplayName + " activation error: ";

            // Get an object representing either the current website (if the scope is Web)
            // or the root website (if the scope is Site).
            SPWeb web = properties.Feature.Parent as SPWeb;
            if (web == null)
            {
                SPSite site = properties.Feature.Parent as SPSite;
                if (site != null)
                    web = site.RootWeb;
            }
            if (web == null)
            {
                System.Diagnostics.Trace.WriteLine(logEntry + "Invalid scope");
                return;
            }

            // Get objects for the two lists.
            SPList customers = web.Lists.TryGetList("Contoso Customers");
            SPList orders = web.Lists.TryGetList("Contoso Orders");
            if (customers == null || orders == null)
            {
                System.Diagnostics.Trace.WriteLine(logEntry + "List not found");
                return;
            }

            // Get the fields from the Customers list that will be seen on the Orders list.
            SPField custID, custLName, custFName, custPhone;
            try
            {
                custID = customers.Fields.GetField("ID");
                custFName = customers.Fields.GetField("First Name");
                custLName = customers.Fields.GetField("Last Name");
                custPhone = customers.Fields.GetField("Contact Phone");
            }
            catch (ArgumentException ex)
            {
                // One of the fields was not found on the Customers list.
                System.Diagnostics.Trace.WriteLine(logEntry + ex.Message);
                return;
            }

            /* 
            * Create a multi-column lookup on the Orders list. 
            */

            // Create the primary column: Customer ID.
            string strPrimary = orders.Fields.AddLookup("Customer ID", customers.ID, true);

            SPFieldLookup primary = orders.Fields.GetFieldByInternalName(strPrimary) as SPFieldLookup;
            primary.LookupField = custID.InternalName;
            primary.StaticName = STATIC_CUST_ID;
            primary.Update();

            // Create a secondary column: First Name.
            string strFName = orders.Fields.AddDependentLookup("First Name", primary.Id);

            SPFieldLookup ordersFName = orders.Fields.GetFieldByInternalName(strFName) as SPFieldLookup;
            ordersFName.LookupField = custFName.InternalName;
            ordersFName.StaticName = STATIC_CUST_FNAME;
            ordersFName.Update();

            // Create a secondary column: Last Name.
            string strLName = orders.Fields.AddDependentLookup("Last Name", primary.Id);

            SPFieldLookup ordersLName = orders.Fields.GetFieldByInternalName(strLName) as SPFieldLookup;
            ordersLName.LookupField = custLName.InternalName;
            ordersLName.StaticName = STATIC_CUST_LNAME;
            ordersLName.Update();

            // Create a secondary column: Phone.
            string strPhone = orders.Fields.AddDependentLookup("Phone", primary.Id);

            SPFieldLookup ordersPhone = orders.Fields.GetFieldByInternalName(strPhone) as SPFieldLookup;
            ordersPhone.LookupField = custPhone.InternalName;
            ordersPhone.StaticName = STATIC_CUST_PHONE;
            ordersPhone.Update();

            // Add columns to the default view.
            AddToDefaultView(orders, strFName);
            AddToDefaultView(orders, strLName);
            AddToDefaultView(orders, strPhone);
        }

        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            string logEntry = properties.Definition.DisplayName + " deactivation error: ";

            // Get an object representing either the current website (if the scope is Web)
            // or the root website (if the scope is Site).
            SPWeb web = properties.Feature.Parent as SPWeb;
            if (web == null)
            {
                SPSite site = properties.Feature.Parent as SPSite;
                if (site != null)
                    web = site.RootWeb;
            }
            if (web == null)
            {
                System.Diagnostics.Trace.WriteLine(logEntry + "Invalid scope");
                return;
            }

            // Get the Orders list.
            SPList orders = web.Lists.TryGetList("Contoso Orders");
            if (orders == null)
            {
                System.Diagnostics.Trace.WriteLine(logEntry + "List not found");
                return;
            }

            // Delete the lookup fields.
            // Note that you must delete dependent lookup fields
            // before deleting the primary lookup field.
            SPFieldLookup primaryLookup = orders.Fields.TryGetFieldByStaticName(STATIC_CUST_ID) as SPFieldLookup;
            if (primaryLookup != null && !primaryLookup.IsDependentLookup)
            {
                string[] dependentLookupNames = primaryLookup.GetDependentLookupInternalNames().ToArray();
                if (dependentLookupNames.Length != 0)
                {
                    foreach (string dependent in dependentLookupNames)
                    {
                        orders.Fields.Delete(dependent);
                    }
                }
                primaryLookup.Delete();
            }

        }

        public void AddToDefaultView(SPList list, string fieldName)
        {
            if (list != null && list.Fields.ContainsField(fieldName) && !list.DefaultView.ViewFields.Exists(fieldName))
            {
                SPView defaultView = list.DefaultView;
                defaultView.ViewFields.Add(fieldName);
                defaultView.Update();
            }
        }
    }
}
Option Explicit On
Option Strict On

Imports System
Imports System.Runtime.InteropServices
Imports Microsoft.SharePoint


<GuidAttribute("c17f29fb-670e-41ba-af43-8a1e97c1cae5")> _
Public Class CustomerLookupsEventReceiver 
    Inherits SPFeatureReceiver

    ' Define static field names.
    Const STATIC_CUST_ID As String = "CustID"
    Const STATIC_CUST_FNAME As String = "CustFName"
    Const STATIC_CUST_LNAME As String = "CustLName"
    Const STATIC_CUST_PHONE As String = "CustPhone"

 
    Public Overrides Sub FeatureActivated(ByVal properties As SPFeatureReceiverProperties)
        Dim logEntry As String = properties.Definition.DisplayName + " activation error: "

        ' Get an object representing either the current website (if the scope is Web)
        ' or the root website (if the scope is Site).
        Dim web As SPWeb = TryCast(properties.Feature.Parent, SPWeb)
        If web Is Nothing Then
            Dim site As SPSite = TryCast(properties.Feature.Parent, SPSite)
            If site IsNot Nothing Then
                web = site.RootWeb
            End If
        End If
        If web Is Nothing Then
            System.Diagnostics.Trace.WriteLine(logEntry + "Invalid scope")
            Return
        End If

        ' Get objects for the two lists.
        Dim customers As SPList = web.Lists.TryGetList("Contoso Customers")
        Dim orders As SPList = web.Lists.TryGetList("Contoso Orders")
        If customers Is Nothing OrElse orders Is Nothing Then
            System.Diagnostics.Trace.WriteLine(logEntry + "List not found")
            Return
        End If

        ' Get the fields from the Customers list that will be seen on the Orders list.
        Dim custID, custLName, custFName, custPhone As SPField
        Try
            custID = customers.Fields.GetField("ID")
            custFName = customers.Fields.GetField("First Name")
            custLName = customers.Fields.GetField("Last Name")
            custPhone = customers.Fields.GetField("Contact Phone")
        Catch ex As ArgumentException

            ' One of the fields was not found on the Customers list.
            System.Diagnostics.Trace.WriteLine(logEntry + ex.Message)
            Return
        End Try

        ' 
        '  Create a multi-column lookup on the Orders list. 
        '            

        ' Create the primary column: Customer ID.
        Dim strPrimary As String = orders.Fields.AddLookup("Customer ID", customers.ID, True)

        Dim primary As SPFieldLookup = TryCast(orders.Fields.GetFieldByInternalName(strPrimary), SPFieldLookup)
        primary.LookupField = custID.InternalName
        primary.StaticName = STATIC_CUST_ID
        primary.Update()

        ' Create a secondary column: First Name.
        Dim strFName As String = orders.Fields.AddDependentLookup("First Name", primary.Id)

        Dim ordersFName As SPFieldLookup = TryCast(orders.Fields.GetFieldByInternalName(strFName), SPFieldLookup)
        ordersFName.LookupField = custFName.InternalName
        ordersFName.StaticName = STATIC_CUST_FNAME
        ordersFName.Update()

        ' Create a secondary column: Last Name.
        Dim strLName As String = orders.Fields.AddDependentLookup("Last Name", primary.Id)

        Dim ordersLName As SPFieldLookup = TryCast(orders.Fields.GetFieldByInternalName(strLName), SPFieldLookup)
        ordersLName.LookupField = custLName.InternalName
        ordersLName.StaticName = STATIC_CUST_LNAME
        ordersLName.Update()

        ' Create a secondary column: Phone.
        Dim strPhone As String = orders.Fields.AddDependentLookup("Phone", primary.Id)

        Dim ordersPhone As SPFieldLookup = TryCast(orders.Fields.GetFieldByInternalName(strPhone), SPFieldLookup)
        ordersPhone.LookupField = custPhone.InternalName
        ordersPhone.StaticName = STATIC_CUST_PHONE
        ordersPhone.Update()

        ' Add columns to the default view.
        AddToDefaultView(orders, strFName)
        AddToDefaultView(orders, strLName)
        AddToDefaultView(orders, strPhone)
    End Sub

    Public Overrides Sub FeatureDeactivating(ByVal properties As SPFeatureReceiverProperties)

        Dim logEntry As String = properties.Definition.DisplayName + " deactivation error: "

        ' Get an object representing either the current website (if the scope is Web)
        ' or the root website (if the scope is Site).
        Dim web As SPWeb = TryCast(properties.Feature.Parent, SPWeb)
        If web Is Nothing Then
            Dim site As SPSite = TryCast(properties.Feature.Parent, SPSite)
            If site IsNot Nothing Then
                web = site.RootWeb
            End If
        End If
        If web Is Nothing Then
            System.Diagnostics.Trace.WriteLine(logEntry + "Invalid scope")
            Return
        End If

        ' Get the Orders list.
        Dim orders As SPList = web.Lists.TryGetList("Contoso Orders")
        If orders Is Nothing Then
            System.Diagnostics.Trace.WriteLine(logEntry + "List not found")
            Return
        End If

        ' Delete the lookup fields.
        ' Note that you must delete dependent lookup fields
        ' before deleting the primary lookup field.
        Dim primaryLookup As SPFieldLookup = TryCast(orders.Fields.TryGetFieldByStaticName(STATIC_CUST_ID), SPFieldLookup)
        If primaryLookup IsNot Nothing AndAlso Not primaryLookup.IsDependentLookup Then
            Dim dependentLookupNames As String() = primaryLookup.GetDependentLookupInternalNames().ToArray()
            If dependentLookupNames.Length > 0 Then
                For Each dependent As String In dependentLookupNames
                    orders.Fields.Delete(dependent)
                Next
            End If
            primaryLookup.Delete()
        End If

    End Sub

    Public Sub AddToDefaultView(ByVal list As SPList, ByVal fieldName As String)
        If list IsNot Nothing AndAlso list.Fields.ContainsField(fieldName) AndAlso Not list.DefaultView.ViewFields.Exists(fieldName) Then
            Dim defaultView As SPView = list.DefaultView
            defaultView.ViewFields.Add(fieldName)
            defaultView.Update()
        End If
    End Sub

End Class

Voir aussi

Référence

Field, élément (Field)

SPFieldLookup

AddLookup(String, Guid, Boolean)

AddDependentLookup(String, Guid)

Concepts

Recherches et relations de liste