Verwenden des regelbasierten Benutzeroberflächenkontexts für Visual Studio-Erweiterungen
Visual Studio ermöglicht das Laden von VSPackages, wenn bestimmte bekannte UIContexts aktiviert werden. Diese UI-Kontexte sind jedoch nicht fein abgestimmt, sodass Erweiterungsautoren keine Wahl haben, sondern einen verfügbaren UI-Kontext auswählen, der aktiviert wird, bevor der Punkt aktiviert wird, an dem die VSPackage geladen werden soll. Eine Liste bekannter UI-Kontexte finden Sie unter KnownUIContexts.
Das Laden von Paketen kann Auswirkungen auf die Leistung haben und das Laden früher als erforderlich ist nicht die bewährte Methode. Visual Studio 2015 hat das Konzept regelbasierter Benutzeroberflächenkontexte eingeführt, einen Mechanismus, mit dem Erweiterungsautoren die genauen Bedingungen definieren können, unter denen ein UI-Kontext aktiviert und zugeordnete VSPackages geladen werden.
Regelbasierter Benutzeroberflächenkontext
Eine „Regel“ besteht aus einem neuen UI-Kontext (einer GUID) und einem booleschen Ausdruck, der auf einen oder mehrere „Begriffe“ in Kombination mit logischen „and“-, „or“- oder „not“-Vorgängen verweist. „Ausdrücke“ werden zur Laufzeit dynamisch ausgewertet, und der Ausdruck wird bei jeder Änderung seiner Begriffe erneut ausgewertet. Wenn der Ausdruck als true ausgewertet wird, wird der zugeordnete UI-Kontext aktiviert. Andernfalls wird der UI-Kontext deaktiviert.
Regelbasierter Benutzeroberflächenkontext kann auf verschiedene Arten verwendet werden:
Geben Sie Sichtbarkeitseinschränkungen für Befehle und Toolfenster an. Sie können die Fenster für Befehle/Tools ausblenden, bis die UI-Kontextregel erfüllt ist.
Als Einschränkungen beim automatischen Laden: Pakete nur dann automatisch laden, wenn die Regel erfüllt ist.
Als verzögerter Vorgang: Verzögertes Laden, bis ein angegebenes Intervall überschritten wurde und die Regel noch erfüllt ist.
Der Mechanismus kann von jeder Visual Studio-Erweiterung verwendet werden.
Erstellen eines regelbasierten Benutzeroberflächenkontexts
Angenommen, Sie haben eine Erweiterung namens TestPackage, die einen Menübefehl bietet, der nur für Dateien mit der Erweiterung CONFIG gilt. Vor VS2015 war die beste Option, TestPackage beim SolutionExistsAndFullyLoadedContext Aktivieren des UI-Kontexts zu laden. Das Laden von TestPackage auf diese Weise ist nicht effizient, da die geladene Lösung möglicherweise nicht einmal eine CONFIG-Datei enthält. Diese Schritte zeigen, wie regelbasierter Benutzeroberflächenkontext verwendet werden kann, um einen UI-Kontext nur zu aktivieren, wenn eine Datei mit der Config-Erweiterung ausgewählt ist, und TestPackage laden, wenn dieser UI-Kontext aktiviert wird.
Definieren Sie eine neue UIContext-GUID, und fügen Sie der VSPackage-Klasse ProvideAutoLoadAttribute und ProvideUIContextRuleAttribute.
Nehmen wir beispielsweise an, dass ein neuer UIContext „UIContextGuid“ hinzugefügt werden soll. Die erstellte GUID (Sie können eine GUID erstellen, indem Sie auf Tools>create GUID) klicken, lautet „8B40D5E2-5626-42AE-99EF-3DD1EFF46E7B“. Anschließend fügen Sie die folgende Deklaration in Der Paketklasse hinzu:
public const string UIContextGuid = "8B40D5E2-5626-42AE-99EF-3DD1EFF46E7B";
Fügen Sie für die Attribute die folgenden Werte hinzu: (Details zu diesen Attributen werden später erläutert)
[ProvideAutoLoad(TestPackage.UIContextGuid)] [ProvideUIContextRule(TestPackage.UIContextGuid, name: "Test auto load", expression: "DotConfig", termNames: new[] { "DotConfig" }, termValues: new[] { "HierSingleSelectionName:.config$" })]
Diese Metadaten definieren die neue UIContext-GUID (8B40D5E2-5626-42AE-99EF-3DD1EFF46E7B) und einen Ausdruck, der auf einen einzelnen Ausdruck verweist, „DotConfig“. Der Ausdruck „DotConfig“ wird auf „true“ ausgewertet, wenn die aktuelle Auswahl in der aktiven Hierarchie einen Namen aufweist, der mit dem Muster für reguläre Ausdrücke „\.config$“ übereinstimmt (endet mit .config). Der Wert (Standardwert) definiert einen optionalen Namen für die Regel, die für das Debuggen nützlich ist.
Die Werte des Attributs werden anschließend zu pkgdef hinzugefügt, die während der Buildzeit generiert wurden.
Fügen Sie in der VSCT-Datei für die Befehle von TestPackage das Flag „DynamicVisibility“ den entsprechenden Befehlen hinzu:
<CommandFlag>DynamicVisibility</CommandFlag>
Verknüpfen Sie im Abschnitt VisibilityConstraints des VSCT die entsprechenden Befehle mit der in #1 definierten neuen UIContext-GUID:
<VisibilityConstraints> <VisibilityItem guid="guidTestPackageCmdSet" id="TestId" context="UIContextGuid"/> </VisibilityConstraints>
Fügen Sie im Abschnitt Symbole die Definition des UIContext hinzu:
<GuidSymbol name="UIContextGuid" value="{8B40D5E2-5626-42AE-99EF-3DD1EFF46E7B}" />
Jetzt werden die Kontextmenübefehle für *.config-Dateien nur angezeigt, wenn das ausgewählte Element im Projektmappen-Explorer eine CONFIG-Datei ist und das Paket erst geladen wird, wenn einer dieser Befehle ausgewählt ist.
Verwenden Sie als Nächstes einen Debugger, um zu bestätigen, dass das Paket nur geladen wird, wenn es erwartet wird. So debuggen Sie TestPackage:
Legen Sie in einen Breakpoint in der Initialize-Methode fest.
Erstellen Sie das TestPackage, und starten Sie das Debuggen.
Erstellen oder öffnen Sie ein Projekt.
Wählen Sie eine beliebige Datei mit einer anderen Erweiterung als .config aus. Der Haltepunkt sollte nicht getroffen werden.
Wählen Sie die Datei App.config.
Das TestPackage lädt und stoppt am Breakpoint.
Hinzufügen weiterer Regeln für ui-Kontext
Da es sich bei den Benutzeroberflächenkontextregeln um boolesche Ausdrücke handelt, können Sie für einen UI-Kontext weitere eingeschränkte Regeln hinzufügen. Im obigen Benutzeroberflächenkontext können Sie beispielsweise angeben, dass die Regel nur gilt, wenn eine Projektmappe mit einem Projekt geladen wird. Auf diese Weise werden die Befehle nicht angezeigt, wenn Sie eine CONFIG-Datei als eigenständige Datei öffnen, nicht als Teil eines Projekts.
[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$" })]
Der Ausdruck verweist nun auf drei Ausdrücke. Die ersten beiden Begriffe „SingleProject“ und „MultipleProjects“ beziehen sich auf andere bekannte UI-Kontexte (anhand ihrer GUIDs). Der dritte Begriff „DotConfig“ ist der regelbasierte UI-Kontext, der weiter oben in diesem Artikel definiert wurde.
Verzögerte Aktivierung
Regeln können eine optionale „Verzögerung“ aufweisen. Die Verzögerung wird in Millisekunden angegeben. Wenn vorhanden, bewirkt die Verzögerung, dass die Aktivierung oder Deaktivierung des UI-Kontexts einer Regel um dieses Zeitintervall verzögert wird. Wenn sich die Regel vor dem Verzögerungsintervall wieder ändert, geschieht nichts. Dieser Mechanismus kann verwendet werden, um Initialisierungsschritte zu „gestaffelt“ – insbesondere einmalige Initialisierung, ohne zeitgesteuerte Benachrichtigungen zu verwenden oder sich für Leerlaufbenachrichtigungen zu registrieren.
Sie können beispielsweise die Testladeregel angeben, um eine Verzögerung von 100 Millisekunden zu haben:
[ProvideAutoLoad(TestPackage.UIContextGuid)]
[ProvideUIContextRule(TestPackage.UIContextGuid,
name: "Test auto load",
expression: "DotConfig",
termNames: new[] { "DotConfig" },
termValues: new[] { "HierSingleSelectionName:.config$" },
delay: 100)]
Ausdruckstypen
Hier sind die verschiedenen Arten von Begriffen, die unterstützt werden:
Begriff | Beschreibung |
---|---|
{nnnnnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn} | Die GUID bezieht sich auf einen UI-Kontext. Der Ausdruck ist true, wenn der UI-Kontext aktiv ist und andernfalls false ist. |
HierSingleSelectionName:<pattern> | Der Ausdruck ist wahr, wenn die Auswahl in der aktiven Hierarchie ein einzelnes Element ist und der Name des ausgewählten Elements dem regulären .NET-Ausdruck entspricht, der durch „pattern“ angegeben wird. |
UserSettingsStoreQuery:<query> | „query“ stellt einen vollständigen Pfad zum Informationsspeicher für Benutzereinstellungen dar, der zu einem Wert ungleich Null ausgewertet werden muss. Die Abfrage wird in eine „Sammlung“ und „propertyName“ am letzten Schrägstrich aufgeteilt. |
Config Einstellungen StoreQuery:<query> | „query“ stellt einen vollständigen Pfad zum Konfigurationseinstellungsspeicher dar, der zu einem Wert ungleich Null ausgewertet werden muss. Die Abfrage wird in eine „Sammlung“ und „propertyName“ am letzten Schrägstrich aufgeteilt. |
ActiveProjectFlavor:<projectTypeGuid> | Der Begriff ist wahr, wenn das aktuell ausgewählte Projekt aromatisiert (aggregiert) ist und einen Geschmack aufweist, der der angegebenen Projekttyp-GUID entspricht. |
ActiveEditorContentType:<contentType> | Der Ausdruck ist wahr, wenn das ausgewählte Dokument ein Text-Editor mit dem angegebenen Inhaltstyp ist. Hinweis: Wenn das ausgewählte Dokument umbenannt wird, wird dieser Ausdruck erst aktualisiert, wenn die Datei geschlossen und erneut geöffnet wird. |
ActiveProjectCapability:<Expression> | Der Begriff ist wahr, wenn aktive Projektfunktionen mit dem bereitgestellten Ausdruck übereinstimmen. Ein Ausdruck kann etwa VB | Csharp. |
SolutionHasProjectCapability:<Expression> | Ähnlich wie oben, aber der Begriff ist wahr, wenn die Lösung ein geladenes Projekt enthält, das mit dem Ausdruck übereinstimmt. |
SolutionHasProjectFlavor:<projectTypeGuid> | Der Begriff gilt immer dann, wenn eine Projektmappe projektiert (aggregiert) hat und einen Geschmack aufweist, der der angegebenen Projekttyp-GUID entspricht. |
ProjectAddedItem:<pattern> | Der Begriff ist wahr, wenn eine Datei, die dem „Muster“ entspricht, zu einem Projekt in der projektmappe hinzugefügt wird, die geöffnet wird. |
ActiveProjectOutputType:<outputType> | Der Ausdruck ist wahr, wenn der Ausgabetyp für aktives Projekt exakt übereinstimmt. Der outputType kann eine ganze Zahl oder ein __VSPROJOUTPUTTYPE Typ sein. |
ActiveProjectBuildProperty:<buildProperty>=<regex> | Der Ausdruck ist wahr, wenn das aktive Projekt die angegebene Buildeigenschaft und den Angegebenen Eigenschaftswert mit dem angegebenen regex-Filter übereinstimmt. Weitere Informationen zu Buildeigenschaften finden Sie unter Speichern von Daten in MSBuild-Projektdateien. |
SolutionHasProjectBuildProperty:<buildProperty>=<regex> | Der Begriff ist wahr, wenn die Lösung ein geladenes Projekt mit den angegebenen Buildeigenschafts- und Eigenschaftswert-Übereinstimmungen mit dem bereitgestellten regex-Filter aufweist. |
Kompatibilität mit versionsübergreifender Erweiterung
Regelbasierte UI-Kontexte sind ein neues Feature in Visual Studio 2015 und würden nicht zu früheren Versionen portiert werden. Das Portieren zu früheren Versionen verursacht ein Problem mit Erweiterungen/Paketen, die auf mehrere Versionen von Visual Studio abzielen. Diese Versionen müssen in Visual Studio 2013 und früher automatisch geladen werden, können aber von regelbasierten UI-Kontexten profitieren, um das automatische Laden in Visual Studio 2015 zu verhindern.
Um solche Pakete zu unterstützen, können AutoLoadPackages-Einträge in der Registrierung jetzt ein Flag in seinem Wertfeld bereitstellen, um anzugeben, dass der Eintrag in Visual Studio 2015 und höher übersprungen werden soll. Dazu können Sie eine Kennzeichnungsoption hinzufügen.PackageAutoLoadFlags VSPackages können nun die Option SkipWhenUIContextRulesActive zu ihrem ProvideAutoLoadAttribute Attribut hinzufügen, um anzugeben, dass der Eintrag in Visual Studio 2015 und höher ignoriert werden soll.
Erweiterbare Benutzeroberflächenkontextregeln
Manchmal können Pakete keine statischen Benutzeroberflächenkontextregeln verwenden. Angenommen, Sie verfügen über ein Paket, das die Erweiterbarkeit unterstützt, sodass der Befehlsstatus auf Editortypen basiert, die von importierten MEF-Anbietern unterstützt werden. Der Befehl ist aktiviert, wenn eine Erweiterung den aktuellen Bearbeitungstyp unterstützt. In solchen Fällen kann das Paket selbst keine statische Benutzeroberflächenkontextregel verwenden, da sich die Begriffe je nach verfügbaren MEF-Erweiterungen ändern würden.
Um solche Pakete zu unterstützen, unterstützen regelbasierte UI-Kontexte einen hartcodierten Ausdruck „*“, der alle unten aufgeführten Ausdrücke angibt, die mit OR verknüpft werden. Dadurch kann das Masterpaket einen bekannten regelbasierten UI-Kontext definieren und den Befehlsstatus mit diesem Kontext verknüpfen. Anschließend kann jede für das Masterpaket gezielte MEF-Erweiterung ihre Ausdrücke für Editoren hinzufügen, die unterstützt werden, ohne dass andere Ausdrücke oder der Masterausdruck beeinträchtigt werden.
Die Konstruktordokumentation ProvideExtensibleUIContextRuleAttribute zeigt die Syntax für erweiterbare UI-Kontextregeln.