Udostępnij za pośrednictwem


Używanie kontekstu interfejsu użytkownika opartego na regułach dla rozszerzeń programu Visual Studio

Program Visual Studio umożliwia ładowanie pakietów VSPackage w przypadku aktywowania określonych dobrze znanych UIContextelementów. Jednak te konteksty interfejsu użytkownika nie są szczegółowe, co pozostawia autorom rozszerzeń bez wyboru, ale wybranie dostępnego kontekstu interfejsu użytkownika, który aktywuje się przed punktem, w którym naprawdę chciał załadować pakiet VSPackage. Aby uzyskać listę dobrze znanych kontekstów interfejsu użytkownika, zobacz KnownUIContexts.

Ładowanie pakietów może mieć wpływ na wydajność i ładowanie ich wcześniej niż jest to konieczne, nie jest najlepszym rozwiązaniem. Program Visual Studio 2015 wprowadził koncepcję kontekstów interfejsu użytkownika opartego na regułach, mechanizmu, który umożliwia autorom rozszerzeń definiowanie dokładnych warunków, w których kontekst interfejsu użytkownika jest aktywowany i ładowane są skojarzone pakiety VSPackage.

Kontekst interfejsu użytkownika opartego na regułach

Reguła składa się z nowego kontekstu interfejsu użytkownika (identyfikatora GUID) i wyrażenia logicznego odwołującego się do co najmniej jednego "warunków" w połączeniu z logicznymi operacjami "and", "or", "not". Terminy są obliczane dynamicznie w czasie wykonywania, a wyrażenie jest ponownie oceniane za każdym razem, gdy dowolny z jego terminów ulegnie zmianie. Gdy wyrażenie zwróci wartość true, skojarzony kontekst interfejsu użytkownika jest aktywowany. W przeciwnym razie kontekst interfejsu użytkownika jest deaktywowany.

Kontekst interfejsu użytkownika oparty na regułach może być używany na różne sposoby:

  1. Określ ograniczenia widoczności dla poleceń i okien narzędzi. Możesz ukryć okna poleceń/narzędzi, dopóki reguła kontekstu interfejsu użytkownika nie zostanie spełniona.

  2. Jako ograniczenia automatycznego ładowania: pakiety automatycznego ładowania są ładowane tylko wtedy, gdy reguła jest spełniona.

  3. Jako zadanie opóźnione: opóźnienie ładowania do czasu przekazania określonego interwału i reguła jest nadal spełniona.

    Mechanizm może być używany przez dowolne rozszerzenie programu Visual Studio.

Tworzenie kontekstu interfejsu użytkownika opartego na regułach

Załóżmy, że masz rozszerzenie o nazwie TestPackage, które oferuje polecenie menu, które ma zastosowanie tylko do plików z rozszerzeniem config . Przed programem VS2015 najlepszym rozwiązaniem było załadowanie pakietu TestPackage po SolutionExistsAndFullyLoadedContext aktywowaniu kontekstu interfejsu użytkownika. Ładowanie pakietu TestPackage w ten sposób nie jest wydajne, ponieważ załadowane rozwiązanie może nawet nie zawierać pliku .config . Te kroki pokazują, jak kontekst interfejsu użytkownika oparty na regułach może służyć do aktywowania kontekstu interfejsu użytkownika tylko wtedy, gdy wybrano plik z rozszerzeniem config i załaduj pakiet TestPackage po aktywowaniu tego kontekstu interfejsu użytkownika.

  1. Zdefiniuj nowy identyfikator GUID interfejsu użytkownikaContext i dodaj go do klasy ProvideAutoLoadAttribute VSPackage i ProvideUIContextRuleAttribute.

    Załóżmy na przykład, że należy dodać nowy element UIContextGuid "UIContextGuid". Utworzony identyfikator GUID (można utworzyć identyfikator GUID, klikając pozycję Narzędzia>Utwórz identyfikator GUID) to "8B40D5E2-5626-42AE-99EF-3DD1EFF46E7B". Następnie dodasz następującą deklarację wewnątrz klasy pakietu:

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

    W przypadku atrybutów dodaj następujące wartości: (Szczegóły tych atrybutów zostaną wyjaśnione później)

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

    Te metadane definiują nowy identyfikator GUID interfejsu użytkownika (8B40D5E2-5626-42AE-99EF-3DD1EFF46E7B) i wyrażenie odwołujące się do jednego terminu "DotConfig". Termin "DotConfig" daje wartość true za każdym razem, gdy bieżące zaznaczenie w aktywnej hierarchii ma nazwę zgodną ze wzorcem wyrażenia regularnego "\.config$" (kończy się ciągiem .config). Wartość (Wartość domyślna) definiuje opcjonalną nazwę reguły przydatnej do debugowania.

    Wartości atrybutu są dodawane do pliku pkgdef wygenerowanego w czasie kompilacji później.

  2. W pliku VSCT poleceń narzędzia TestPackage dodaj flagę "DynamicVisibility" do odpowiednich poleceń:

    <CommandFlag>DynamicVisibility</CommandFlag>
    
  3. W sekcji Ograniczenia widoczności programu VSCT należy powiązać odpowiednie polecenia z nowym identyfikatorem GUID interfejsu użytkownikaContext zdefiniowanym w pliku #1:

    <VisibilityConstraints>
        <VisibilityItem guid="guidTestPackageCmdSet" id="TestId"  context="UIContextGuid"/>
    </VisibilityConstraints>
    
  4. W sekcji Symbole dodaj definicję interfejsu użytkownikaContext:

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

    Teraz polecenia menu kontekstowego dla plików *.config będą widoczne tylko wtedy, gdy wybrany element w Eksploratorze rozwiązań jest plikiem .config, a pakiet nie zostanie załadowany do momentu wybrania jednego z tych poleceń.

    Następnie użyj debugera, aby potwierdzić, że pakiet jest ładowany tylko wtedy, gdy oczekujesz. Aby debugować pakiet TestPackage:

  5. Ustaw punkt przerwania w metodzie Initialize .

  6. Skompiluj pakiet TestPackage i rozpocznij debugowanie.

  7. Utwórz projekt lub otwórz go.

  8. Wybierz dowolny plik z rozszerzeniem innym niż .config. Punkt przerwania nie powinien być trafiony.

  9. Wybierz plik App.Config.

    Pakiet TestPackage ładuje i zatrzymuje się w punkcie przerwania.

Dodawanie kolejnych reguł dla kontekstu interfejsu użytkownika

Ponieważ reguły kontekstu interfejsu użytkownika są wyrażeniami logicznymi, można dodać bardziej ograniczone reguły dla kontekstu interfejsu użytkownika. Na przykład w powyższym kontekście interfejsu użytkownika można określić, że reguła ma zastosowanie tylko w przypadku załadowania rozwiązania z projektem. W ten sposób polecenia nie będą wyświetlane, jeśli otworzysz plik config jako plik autonomiczny, a nie jako część projektu.

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

Teraz wyrażenie odwołuje się do trzech terminów. Dwa pierwsze terminy: "SingleProject" i "MultipleProjects" odnoszą się do innych dobrze znanych kontekstów interfejsu użytkownika (według ich identyfikatorów GUID). Trzeci termin "DotConfig" to kontekst interfejsu użytkownika oparty na regułach zdefiniowany wcześniej w tym artykule.

Opóźniona aktywacja

Reguły mogą mieć opcjonalną wartość "Opóźnienie". Opóźnienie jest określone w milisekundach. Jeśli jest obecny, opóźnienie powoduje, że aktywacja lub dezaktywacja kontekstu interfejsu użytkownika reguły jest opóźniona o ten przedział czasu. Jeśli reguła zmieni się z powrotem przed interwałem opóźnienia, nic się nie stanie. Ten mechanizm może służyć do "rozsyłania" kroków inicjowania — zwłaszcza jednorazowej inicjowania bez polegania na czasomierzach lub rejestrowaniu w przypadku bezczynnych powiadomień.

Możesz na przykład określić regułę obciążenia testowego, aby mieć opóźnienie 100 milisekund:

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

Typy terminów

Oto różne typy terminów, które są obsługiwane:

Okres opis
{nnnnnnnnnn-nnnn-nnnn-nnnn-nnnn} Identyfikator GUID odnosi się do kontekstu interfejsu użytkownika. Termin będzie spełniony, gdy kontekst interfejsu użytkownika jest aktywny i w przeciwnym razie będzie mieć wartość false.
HierSingleSelectionName:<pattern> Termin będzie spełniony za każdym razem, gdy wybór w aktywnej hierarchii jest pojedynczym elementem, a nazwa wybranego elementu jest zgodna z wyrażeniem regularnym platformy .NET podanym przez "pattern".
User Ustawienia StoreQuery:<query> Wyrażenie "query" reprezentuje pełną ścieżkę do magazynu ustawień użytkownika, który musi mieć wartość inną niż zero. Zapytanie jest podzielone na "kolekcja" i "propertyName" na ostatnim ukośniku.
Konfiguracja Ustawienia StoreQuery:<query> Wyrażenie "query" reprezentuje pełną ścieżkę do magazynu ustawień konfiguracji, który musi mieć wartość inną niż zero. Zapytanie jest podzielone na "kolekcja" i "propertyName" na ostatnim ukośniku.
ActiveProjectFlavor:<projectTypeGuid> Termin będzie spełniony za każdym razem, gdy aktualnie wybrany projekt zostanie zagregowany (zagregowany) i będzie miał smak pasujący do danego identyfikatora GUID typu projektu.
ActiveEditorContentType:<contentType> Termin będzie spełniony, gdy wybrany dokument jest edytorem tekstów z danym typem zawartości. Uwaga: po zmianie nazwy wybranego dokumentu ten termin nie zostanie odświeżony do momentu zamknięcia i ponownego otwarcia pliku.
ActiveProjectCapability:<Expression> Termin ma wartość true, gdy aktywne możliwości projektu są zgodne z podanym wyrażeniem. Wyrażenie może być podobne do vb | Csharp.
SolutionHasProjectCapability:<Expression> Podobnie jak powyżej, ale termin ma wartość true, gdy rozwiązanie ma załadowany projekt zgodny z wyrażeniem.
SolutionHasProjectFlavor:<projectTypeGuid> Termin będzie spełniony za każdym razem, gdy rozwiązanie ma projekt o smaku (zagregowanym) i ma smak pasujący do danego identyfikatora GUID typu projektu.
ProjectAddedItem:<pattern> Termin ma wartość true, gdy plik pasujący do "wzorca" jest dodawany do projektu w otwartym rozwiązaniu.
ActiveProjectOutputType:<outputType> Termin ma wartość true, gdy typ danych wyjściowych aktywnego projektu jest dokładnie zgodny. Typ outputType może być liczbą całkowitą lub typem __VSPROJOUTPUTTYPE .
ActiveProjectBuildProperty:<buildProperty>=<regex> Termin ma wartość true, gdy aktywny projekt ma określoną właściwość kompilacji, a wartość właściwości jest zgodna z podanym filtrem wyrażeń regularnych. Aby uzyskać więcej informacji na temat właściwości kompilacji, zobacz Utrwalanie danych w plikach projektu MSBuild.
SolutionHasProjectBuildProperty:<buildProperty>=<regex> Termin ma wartość true, gdy rozwiązanie ma załadowany projekt z określoną właściwością kompilacji i wartością właściwości pasuje do podanego filtru regex.

Zgodność z rozszerzeniem między wersjami

Konteksty interfejsu użytkownika oparte na regułach są nową funkcją w programie Visual Studio 2015 i nie zostaną przeniesione do wcześniejszych wersji. Przenoszenie do wcześniejszych wersji powoduje problem z rozszerzeniami/pakietami przeznaczonymi dla wielu wersji programu Visual Studio. Te wersje musiałyby być ładowane automatycznie w programie Visual Studio 2013 i starszych wersjach, ale mogą korzystać z kontekstów interfejsu użytkownika opartych na regułach, aby zapobiec automatycznemu ładowaniu w programie Visual Studio 2015.

Aby obsługiwać takie pakiety, wpisy AutoLoadPackages w rejestrze mogą teraz podać flagę w polu wartości, aby wskazać, że wpis powinien zostać pominięty w programie Visual Studio 2015 lub nowszym. Można to zrobić, dodając opcję flagi do PackageAutoLoadFlagselementu . Pakiety VSPackage mogą teraz dodawać opcję SkipWhenUIContextRulesActive do ich ProvideAutoLoadAttribute atrybutu, aby wskazać, że wpis powinien zostać zignorowany w programie Visual Studio 2015 lub nowszym.

Rozszerzalne reguły kontekstu interfejsu użytkownika

Czasami pakiety nie mogą używać statycznych reguł kontekstu interfejsu użytkownika. Załóżmy na przykład, że masz pakiet obsługujący rozszerzalność, tak aby stan polecenia był oparty na typach edytora obsługiwanych przez zaimportowanych dostawców MEF. Polecenie jest włączone, jeśli istnieje rozszerzenie obsługujące bieżący typ edycji. W takich przypadkach sam pakiet nie może używać statycznej reguły kontekstu interfejsu użytkownika, ponieważ terminy zmieniłyby się w zależności od dostępnych rozszerzeń MEF.

Aby obsługiwać takie pakiety, konteksty interfejsu użytkownika oparte na regułach obsługują zakodowane na stałe wyrażenie "*", które wskazuje wszystkie poniższe terminy zostaną dołączone do or. Dzięki temu pakiet główny może zdefiniować znany kontekst interfejsu użytkownika oparty na regułach i powiązać jego stan polecenia z tym kontekstem. Następnie każde rozszerzenie MEF przeznaczone dla pakietu głównego może dodać jego terminy dla edytorów, które obsługuje bez wpływu na inne terminy lub wyrażenie główne.

W dokumentacji konstruktora ProvideExtensibleUIContextRuleAttribute przedstawiono składnię rozszerzalnych reguł kontekstu interfejsu użytkownika.