Condividi tramite


Usare il contesto dell'interfaccia utente basato su regole per le estensioni di Visual Studio

Visual Studio consente il caricamento di VSPackage quando vengono attivati determinati oggetti noti UIContext. Tuttavia, questi contesti dell'interfaccia utente non sono granulari, che lasciano gli autori di estensioni non scelta, ma per selezionare un contesto dell'interfaccia utente disponibile che si attiva prima del punto in cui volevano effettivamente caricare il VSPackage. Per un elenco di contesti noti dell'interfaccia utente, vedere KnownUIContexts.

Il caricamento dei pacchetti può avere un impatto sulle prestazioni e il caricamento prima del necessario non è la procedura consigliata. Visual Studio 2015 ha introdotto il concetto di contesti dell'interfaccia utente basati su regole, un meccanismo che consente agli autori di estensioni di definire le condizioni precise in cui viene attivato un contesto dell'interfaccia utente e i pacchetti VSPackage associati vengono caricati.

Contesto dell'interfaccia utente basato su regole

Una "regola" è costituita da un nuovo contesto dell'interfaccia utente (un GUID) e da un'espressione booleana che fa riferimento a uno o più "Termini" combinati con operazioni logiche "e", "o", "not". "Termini" vengono valutati in modo dinamico in fase di esecuzione e l'espressione viene rivalutata ogni volta che uno dei relativi termini cambia. Quando l'espressione restituisce true, viene attivato il contesto dell'interfaccia utente associato. In caso contrario, il contesto dell'interfaccia utente viene disattivato.

Il contesto dell'interfaccia utente basato su regole può essere usato in diversi modi:

  1. Specificare i vincoli di visibilità per i comandi e le finestre degli strumenti. È possibile nascondere le finestre dei comandi o degli strumenti fino a quando non viene soddisfatta la regola del contesto dell'interfaccia utente.

  2. Come vincoli di caricamento automatico: i pacchetti di caricamento automatico vengono caricati automaticamente solo quando viene soddisfatta la regola.

  3. Come attività ritardata: ritardare il caricamento fino a quando non viene superato un intervallo specificato e la regola viene ancora soddisfatta.

    Il meccanismo può essere usato da qualsiasi estensione di Visual Studio.

Creare un contesto dell'interfaccia utente basato su regole

Si supponga di avere un'estensione denominata TestPackage, che offre un comando di menu che si applica solo ai file con estensione config . Prima di VS2015, l'opzione migliore era caricare TestPackage quando SolutionExistsAndFullyLoadedContext è stato attivato il contesto dell'interfaccia utente. Il caricamento di TestPackage in questo modo non è efficiente, poiché la soluzione caricata potrebbe non contenere nemmeno un file config . Questi passaggi illustrano come usare il contesto dell'interfaccia utente basato su regole per attivare un contesto dell'interfaccia utente solo quando viene selezionato un file con estensione config e caricare TestPackage quando tale contesto dell'interfaccia utente viene attivato.

  1. Definire un nuovo GUID UIContext e aggiungere alla classe ProvideAutoLoadAttribute VSPackage e ProvideUIContextRuleAttribute.

    Si supponga, ad esempio, che venga aggiunta una nuova interfaccia utenteContext "UIContextGuid". Il GUID creato (è possibile creare un GUID facendo clic su Strumenti>Crea GUID) è "8B40D5E2-5626-42AE-99EF-3DD1EFF46E7B". Aggiungere quindi la dichiarazione seguente all'interno della classe del pacchetto:

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

    Per gli attributi, aggiungere i valori seguenti: (i dettagli di questi attributi verranno illustrati più avanti)

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

    Questi metadati definiscono il nuovo GUID UIContext (8B40D5E2-5626-42AE-99EF-3DD1EFF46E7B) e un'espressione che fa riferimento a un singolo termine, "DotConfig". Il termine "DotConfig" restituisce true ogni volta che la selezione corrente nella gerarchia attiva ha un nome corrispondente al modello di espressione regolare "\.config$" (termina con .config). Il valore (predefinito) definisce un nome facoltativo per la regola utile per il debug.

    I valori dell'attributo vengono aggiunti a pkgdef generato in seguito durante il tempo di compilazione.

  2. Nel file VSCT per i comandi di TestPackage aggiungere il flag "DynamicVisibility" ai comandi appropriati:

    <CommandFlag>DynamicVisibility</CommandFlag>
    
  3. Nella sezione VisibilityConstraints di VSCT associare i comandi appropriati al nuovo GUID UIContext definito in #1:

    <VisibilityConstraints>
        <VisibilityItem guid="guidTestPackageCmdSet" id="TestId"  context="UIContextGuid"/>
    </VisibilityConstraints>
    
  4. Nella sezione Simboli aggiungere la definizione di UIContext:

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

    A questo punto, i comandi di menu di scelta rapida per i file *.config saranno visibili solo quando l'elemento selezionato in Esplora soluzioni è un file con estensione config e il pacchetto non verrà caricato finché non viene selezionato uno di questi comandi.

    Successivamente, usare un debugger per verificare che il pacchetto venga caricato solo quando previsto. Per eseguire il debug di TestPackage:

  5. Impostare un punto di interruzione nel Initialize metodo .

  6. Compilare TestPackage e avviare il debug.

  7. Creare un progetto o aprirne uno.

  8. Selezionare qualsiasi file con estensione diversa da .config. Il punto di interruzione non deve essere raggiunto.

  9. Selezionare il file App.Config .

    TestPackage carica e si arresta in corrispondenza del punto di interruzione.

Aggiungere altre regole per il contesto dell'interfaccia utente

Poiché le regole del contesto dell'interfaccia utente sono espressioni booleane, è possibile aggiungere regole più limitate per un contesto dell'interfaccia utente. Ad esempio, nel contesto dell'interfaccia utente precedente, è possibile specificare che la regola si applica solo quando viene caricata una soluzione con un progetto. In questo modo, i comandi non verranno visualizzati se si apre un file con estensione config come file autonomo, non come parte di un progetto.

[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$" })]

Ora l'espressione fa riferimento a tre termini. I primi due termini, "SingleProject" e "MultipleProjects", fanno riferimento ad altri contesti dell'interfaccia utente noti (in base ai relativi GUID). Il terzo termine "DotConfig" è il contesto dell'interfaccia utente basato su regole definito in precedenza in questo articolo.

Attivazione ritardata

Le regole possono avere un "Ritardo" facoltativo. Il ritardo viene specificato in millisecondi. Se presente, il ritardo fa sì che l'attivazione o la disattivazione del contesto dell'interfaccia utente di una regola venga ritardata da tale intervallo di tempo. Se la regola viene modificata prima dell'intervallo di ritardo, non accade nulla. Questo meccanismo può essere usato per "sfalsare" i passaggi di inizializzazione, in particolare l'inizializzazione monouso senza basarsi sui timer o sulla registrazione per le notifiche inattive.

Ad esempio, è possibile specificare la regola di carico di test per avere un ritardo di 100 millisecondi:

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

Tipi di termini

Ecco i vari tipi di termine supportati:

Termine Descrizione
{nnnnnnnn-nnnn-nnnn-nnnn-nnnnnnnnnn} Il GUID fa riferimento a un contesto dell'interfaccia utente. Il termine sarà true ogni volta che il contesto dell'interfaccia utente è attivo e false in caso contrario.
HierSingleSelectionName:<pattern> Il termine sarà true ogni volta che la selezione nella gerarchia attiva è un singolo elemento e il nome dell'elemento selezionato corrisponde all'espressione regolare .NET specificata da "pattern".
Utente Impostazioni StoreQuery:<query> "query" rappresenta un percorso completo nell'archivio delle impostazioni utente, che deve restituire un valore diverso da zero. La query viene suddivisa in una "raccolta" e "propertyName" nell'ultima barra.
Config Impostazioni StoreQuery:<query> "query" rappresenta un percorso completo nell'archivio delle impostazioni di configurazione, che deve restituire un valore diverso da zero. La query viene suddivisa in una "raccolta" e "propertyName" nell'ultima barra.
ActiveProjectFlavor:<projectTypeGuid> Il termine sarà true ogni volta che il progetto attualmente selezionato viene definito (aggregato) e ha un sapore corrispondente al GUID del tipo di progetto specificato.
ActiveEditorContentType:<contentType> Il termine sarà true quando il documento selezionato è un editor di testo con il tipo di contenuto specificato. Nota: quando il documento selezionato viene rinominato, questo termine non viene aggiornato fino a quando il file non viene chiuso e riaperto.
ActiveProjectCapability:<Expression> Il termine è true quando le funzionalità del progetto attivo corrispondono all'espressione specificata. Un'espressione può essere simile a VB | Csharp.
SolutionHasProjectCapability:<Expression> Analogamente a quanto sopra, ma il termine è true quando la soluzione ha un progetto caricato che corrisponde all'espressione.
SolutionHasProjectFlavor:<projectTypeGuid> Il termine sarà true ogni volta che una soluzione ha un progetto con sapore (aggregato) e ha un sapore corrispondente al GUID del tipo di progetto specificato.
ProjectAddedItem:<pattern> Il termine è true quando un file corrispondente al "pattern" viene aggiunto a un progetto nella soluzione aperta.
ActiveProjectOutputType:<outputType> Il termine è true quando il tipo di output per il progetto attivo corrisponde esattamente. OutputType può essere un numero intero o un __VSPROJOUTPUTTYPE tipo.
ActiveProjectBuildProperty:<buildProperty>=<regex> Il termine è true quando il progetto attivo ha la proprietà di compilazione e il valore della proprietà specificati corrispondono al filtro regex specificato. Per altre informazioni sulle proprietà di compilazione, vedere Rendere persistenti i dati nei file di progetto MSBuild.
SolutionHasProjectBuildProperty:<buildProperty>=<regex> Il termine è true quando la soluzione ha un progetto caricato con la proprietà di compilazione e il valore della proprietà specificati corrisponde al filtro regex fornito.

Compatibilità con l'estensione tra versioni

I contesti dell'interfaccia utente basati su regole sono una nuova funzionalità di Visual Studio 2015 e non vengono trasferiti nelle versioni precedenti. La mancata conversione nelle versioni precedenti crea un problema con estensioni/pacchetti destinati a più versioni di Visual Studio. Queste versioni devono essere caricate automaticamente in Visual Studio 2013 e versioni precedenti, ma possono trarre vantaggio dai contesti dell'interfaccia utente basati su regole per impedire il caricamento automatico in Visual Studio 2015.

Per supportare tali pacchetti, le voci AutoLoadPackages nel Registro di sistema possono ora fornire un flag nel relativo campo valore per indicare che la voce deve essere ignorata in Visual Studio 2015 e versioni successive. A tale scopo, è possibile aggiungere un'opzione flag a PackageAutoLoadFlags. I pacchetti VSPackage possono ora aggiungere l'opzione SkipWhenUIContextRulesActive al relativo ProvideAutoLoadAttribute attributo per indicare che la voce deve essere ignorata in Visual Studio 2015 e versioni successive.

Regole di contesto dell'interfaccia utente estendibili

In alcuni casi, i pacchetti non possono usare regole di contesto dell'interfaccia utente statiche. Si supponga, ad esempio, di avere un pacchetto che supporta l'estendibilità in modo che lo stato del comando sia basato sui tipi di editor supportati dai provider MEF importati. Il comando è abilitato se è presente un'estensione che supporta il tipo di modifica corrente. In questi casi, il pacchetto stesso non può usare una regola di contesto dell'interfaccia utente statica, poiché i termini cambiano a seconda delle estensioni MEF disponibili.

Per supportare tali pacchetti, i contesti dell'interfaccia utente basati su regole supportano un'espressione hardcoded "*" che indica tutti i termini seguenti che verrà unita a OR. Ciò consente al pacchetto master di definire un contesto dell'interfaccia utente basato su regole noto e collegarne lo stato del comando a questo contesto. Successivamente, qualsiasi estensione MEF destinata al pacchetto master può aggiungere i relativi termini per gli editor supportati senza influire su altri termini o sull'espressione master.

La documentazione del costruttore ProvideExtensibleUIContextRuleAttribute mostra la sintassi per le regole di contesto dell'interfaccia utente estendibili.