Partager via


Utiliser le contexte de l’interface utilisateur basé sur une règle pour les extensions Visual Studio

Visual Studio autorise le chargement de VSPackages lorsque certains éléments bien connus UIContext sont activés. Cependant, ces contextes d'IU ne sont pas finement définis, ce qui ne laisse pas d'autre choix aux auteurs d'extensions que de choisir un contexte d'IU disponible qui s'active avant qu'ils ne veuillent vraiment que le VSPackage se charge. Pour une liste des contextes d'IU bien connus, consultez KnownUIContexts.

Le chargement des packages peut avoir un impact sur les performances et les charger plus tôt que nécessaire n'est pas la meilleure pratique. Visual Studio 2015 a introduit le concept de Contextes d'IU basés sur des règles, un mécanisme qui permet aux auteurs d'extensions de définir les conditions précises dans lesquelles un Contexte d'IU est activé et les VSPackages associés sont chargés.

Contexte d’IU basé sur des règles

Une « règle » consiste en un nouveau contexte d'IU (un GUID) et une expression booléenne qui fait référence à un ou plusieurs « Termes » combinés à des opérations logiques « et », « ou », « pas ». Les « Termes » sont évalués dynamiquement au moment de l'exécution et l'expression est réévaluée chaque fois que l'un de ses termes est modifié. Lorsque l'expression est définie sur vrai (true), le contexte d'IU associé est activé. Dans le cas contraire, le contexte de l'IU est désactivé.

Le contexte de l'IU basé sur des règles peut être utilisé de différentes manières :

  1. Spécifiez les contraintes de visibilité pour les commandes et les fenêtres Outils. Vous pouvez masquer les commandes/fenêtres outils jusqu'à ce que la règle du contexte de l'IU soit respectée.

  2. En tant que contraintes de chargement automatique : le chargement automatique des packages n'a lieu que lorsque la règle est respectée.

  3. En tant que tâche retardée : retarder le chargement jusqu'à ce qu'un intervalle spécifié se soit écoulé et que la règle soit toujours respectée.

    Le mécanisme peut être utilisé par n'importe quelle extension de Visual Studio.

Créer un contexte d’IU basé sur des règles

Supposons que vous ayez une extension appelée TestPackage, qui propose une commande de menu qui s'applique uniquement aux fichiers portant l'extension .config. Avant VS2015, la meilleure option était de charger TestPackage lorsque le contexte de l'IU SolutionExistsAndFullyLoadedContext était activé. Le chargement de TestPackage de cette manière n'est pas efficace, car la solution chargée peut ne même pas contenir de fichier .config. Ces étapes montrent comment un contexte d'IU basé sur des règles peut être utilisé pour activer un contexte d'IU uniquement lorsqu'un fichier portant l'extension .config est sélectionné, et pour charger TestPackage lorsque ce contexte d'IU est activé.

  1. Définissez un nouveau GUID UIContext et ajoutez-le à la classe VSPackage ProvideAutoLoadAttribute et ProvideUIContextRuleAttribute.

    Supposons par exemple qu'un nouvel UIContext « UIContextGuid » doive être ajouté. Le GUID créé (vous pouvez créer un GUID en cliquant sur Outils>Créer un GUID) est « 8B40D5E2-5626-42AE-99EF-3DD1EFF46E7B ». Vous ajoutez ensuite la déclaration suivante à l’intérieur de votre classe de package :

    public const string UIContextGuid = "8B40D5E2-5626-42AE-99EF-3DD1EFF46E7B";
    

    Pour les attributs, ajoutez les valeurs suivantes : (Les détails de ces attributs seront expliqués ultérieurement)

    [ProvideAutoLoad(TestPackage.UIContextGuid)]
    [ProvideUIContextRule(TestPackage.UIContextGuid,
        name: "Test auto load",
        expression: "DotConfig",
        termNames: new[] { "DotConfig" },
        termValues: new[] { "HierSingleSelectionName:.config$" })]
    

    Ces métadonnées définissent le nouveau GUID UIContext (8B40D5E2-5626-42AE-99EF-3DD1EFF46E7B) et une expression faisant référence à un terme unique, « DotConfig ». Le terme « DotConfig » est défini sur vrai (true) lorsque la sélection en cours dans la hiérarchie active a un nom qui correspond à l'expression régulière « \.config$ » (se terminant par .config). La valeur (par défaut) définit un nom facultatif pour la règle, utile pour le débogage.

    Les valeurs de l'attribut sont ensuite ajoutées au pkgdef généré lors de la génération.

  2. Dans le fichier VSCT des commandes de TestPackage, ajoutez l'indicateur « DynamicVisibility » aux commandes appropriées :

    <CommandFlag>DynamicVisibility</CommandFlag>
    
  3. Dans la section VisibilityConstraints du VSCT, liez les commandes appropriées au nouveau GUID UIContext défini au point 1 :

    <VisibilityConstraints>
        <VisibilityItem guid="guidTestPackageCmdSet" id="TestId"  context="UIContextGuid"/>
    </VisibilityConstraints>
    
  4. Dans la section Symboles, ajoutez la définition de l'UIContext :

    <GuidSymbol name="UIContextGuid" value="{8B40D5E2-5626-42AE-99EF-3DD1EFF46E7B}" />
    

    Désormais, les commandes de menu local pour les fichiers *.config ne seront visibles que si l'élément sélectionné dans l'explorateur de solutions est un fichier .config et le package ne sera pas chargé tant que l'une de ces commandes n'aura pas été sélectionnée.

    Ensuite, utilisez un débogueur pour confirmer que le package se charge uniquement lorsque vous vous y attendez. Pour déboguer TestPackage :

  5. Définissez un point d’arrêt dans la méthode Initialize.

  6. Générer le TestPackage et démarrez le débogage.

  7. Créez un projet ou ouvrez-en un.

  8. Sélectionnez n'importe quel fichier dont l'extension est différente de .config. Le point d'arrêt ne doit pas être atteint.

  9. Sélectionnez le fichier App.Config.

    Le TestPackage se charge et s'arrête au point d'arrêt.

Ajouter des règles pour le contexte de l'IU

Les règles du contexte de l'IU étant des expressions booléennes, vous pouvez ajouter des règles plus restrictives pour un contexte de l'IU. Par exemple, dans le contexte d'IU ci-dessus, vous pouvez spécifier que la règle ne s'applique que lorsqu'une solution avec un projet est chargée. De cette manière, les commandes n'apparaîtront pas si vous ouvrez un fichier .config en tant que fichier autonome, et non en tant que partie d'un projet.

[ProvideAutoLoad(TestPackage.UIContextGuid)]
[ProvideUIContextRule(TestPackage.UIContextGuid,
    name: "Test auto load",
    expression: "(SingleProject | MultipleProjects) & DotConfig",
    termNames: new[] { "SingleProject", "MultipleProjects","DotConfig" },
    termValues: new[] { VSConstants.UICONTEXT.SolutionHasSingleProject_string , VSConstants.UICONTEXT.SolutionHasMultipleProjects_string , "HierSingleSelectionName:.config$" })]

L'expression fait maintenant référence à trois termes. Les deux premiers termes, « SingleProject » et « MultipleProjects », font référence à d'autres contextes d'IU bien connus (par leur GUID). Le troisième terme, « DotConfig », est le contexte d'IU basé sur des règles, défini plus haut dans cet article.

Activation retardée

Les règles peuvent avoir un « Retard » facultatif. Le retard est spécifié en millisecondes. Le cas échéant, le retard retarde l'activation ou la désactivation du contexte de l'IU d'une règle de cet intervalle de temps. Si la règle change à nouveau avant l'intervalle de retard, il ne se passe rien. Ce mécanisme peut être utilisé pour « échelonner » les étapes d'initialisation – en particulier l'initialisation unique sans dépendre de retardateurs ou de l'enregistrement de notifications d'inactivité.

Par exemple, vous pouvez spécifier que votre règle de charge de test a un retard de 100 millisecondes :

[ProvideAutoLoad(TestPackage.UIContextGuid)]
[ProvideUIContextRule(TestPackage.UIContextGuid,
    name: "Test auto load",
    expression: "DotConfig",
    termNames: new[] { "DotConfig" },
    termValues: new[] { "HierSingleSelectionName:.config$" },
    delay: 100)]

Types de termes

Voici les différents types de termes pris en charge :

Terme Description
{nnnnnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn} Le GUID fait référence à un contexte d’IU. Le terme sera vrai si le contexte de l'IU est actif et faux dans le cas contraire.
HierSingleSelectionName:<pattern> Le terme sera vrai si la sélection dans la hiérarchie active est un élément unique et que le nom de l'élément sélectionné correspond à l'expression régulière .NET donnée par le « modèle ».
UserSettingsStoreQuery:<query> « query » représente un chemin complet dans le magasin de paramètres utilisateur, qui doit être défini sur une valeur non nulle. La requête est fractionnée en « collection » et un « propertyName » au niveau de la dernière barre oblique.
ConfigSettingsStoreQuery:<query> « query » représente un chemin complet dans le magasin de paramètres de configuration, qui doit être défini sur une valeur non nulle. La requête est fractionnée en « collection » et un « propertyName » au niveau de la dernière barre oblique.
ActiveProjectFlavor:<projectTypeGuid> Le terme est vrai chaque fois que le projet actuellement sélectionné est aromatisé (agrégé) et a une saveur correspondant au GUID de type de projet donné.
ActiveEditorContentType:<contentType> Le terme sera vrai si le document sélectionné est un éditeur de texte avec le type de contenu donné. Note : lorsque le document sélectionné est renommé, ce terme n’est pas actualisé tant que le fichier n’est pas fermé et rouvert.
ActiveProjectCapability:<Expression> Le terme sera vrai si les capacités actives du projet correspondent à l'expression fournie. Une expression peut être par exemple VB | CSharp.
SolutionHasProjectCapability:<Expression> Similaire au point précédent mais le terme sera vrai si la solution a un projet chargé qui correspond à l'expression.
SolutionHasProjectFlavor:<projectTypeGuid> Le terme sera vrai chaque fois qu’une solution a un projet qui est aromatisé (agrégé) et a une saveur correspondant au GUID de type de projet donné.
ProjectAddedItem:<pattern> Le terme sera vrai lorsqu'un fichier correspondant au « modèle » est ajouté à un projet dans la solution ouverte.
ActiveProjectOutputType:<outputType> Le terme est vrai si le type de sortie du projet actif correspond exactement. Le outputType peut être un entier ou un type __VSPROJOUTPUTTYPE.
ActiveProjectBuildProperty:<buildProperty>=<regex> Le terme sera vrai si le projet actif a la propriété de version spécifiée et que la valeur de propriété correspond au filtre regex fourni. Consultez la section Persistance des données dans les fichiers de projet MSBuild pour plus de détails sur les propriétés de version.
SolutionHasProjectBuildProperty:<buildProperty>=<regex> Le terme sera vrai si la solution a un projet chargé avec la propriété de version spécifiée et que la valeur de propriété correspond au filtre regex fourni.

Compatibilité avec les extensions de versions

Les contextes d'IU basés sur des règles sont une nouvelle fonctionnalité de Visual Studio 2015 et ne seraient pas portés sur les versions antérieures. Le fait de ne pas prendre en charge les versions antérieures crée un problème avec les extensions/packages qui ciblent plusieurs versions de Visual Studio. Ces versions devraient être chargées automatiquement dans Visual Studio 2013 et les versions antérieures, mais peuvent bénéficier de contextes d'IU basés sur des règles pour éviter d'être chargées automatiquement dans Visual Studio 2015.

Afin de prendre en charge ces packages, les entrées AutoLoadPackages dans le registre peuvent désormais fournir un indicateur dans son champ de valeur pour indiquer que l'entrée doit être ignorée dans Visual Studio 2015 et les versions ultérieures. Pour ce faire, ajoutez une option d’indicateurs à PackageAutoLoadFlags. Les VSPackages peuvent désormais ajouter l'option SkipWhenUIContextRulesActive à leur attribut ProvideAutoLoadAttribute pour indiquer que l'entrée doit être ignorée dans Visual Studio 2015 et les versions ultérieures.

Règles de contexte d’IU extensible

Parfois, les packages ne peuvent pas utiliser les règles statiques du contexte de l'IU. Par exemple, supposons que vous ayez un package prenant en charge l'extensibilité, de sorte que l'état de la commande soit basé sur les types d'éditeurs pris en charge par les fournisseurs MEF importés. La commande est activée s’il existe une extension prenant en charge le type d’édition actuel. Dans ce cas, le package lui-même ne peut pas utiliser une règle statique de contexte d'IU, car les termes changeraient en fonction des extensions MEF disponibles.

Afin de prendre en charge de tels packages, les contextes d'IU basés sur des règles prennent en charge une expression codée en dur « * » qui indique que tous les termes situés en dessous seront combinés avec OU. Cela permet au package master de définir un contexte d’interface utilisateur basé sur des règles connus et de lier son état de commande à ce contexte. Ensuite, toute extension MEF ciblée pour le package master peut ajouter ses termes pour les éditeurs qu'elle prend en charge sans avoir d'impact sur les autres termes ou l'expression Master.

La documentation ProvideExtensibleUIContextRuleAttribute du constructeur présente la syntaxe des règles extensibles du contexte de l'IU.