Przewodnik: tworzenie glyph marginesu

Wygląd marginesów edytora można dostosować przy użyciu niestandardowych rozszerzeń edytora. Ten przewodnik umieszcza niestandardowy glyph na marginesie wskaźnika za każdym razem, gdy słowo "todo" pojawia się w komentarzu kodu.

Tworzenie projektu MEF

  1. Utwórz projekt VSIX w języku C#. (W Okno dialogowe Nowy projekt , wybierz pozycję Visual C# / Rozszerzalność, a następnie projekt VSIX. Nadaj rozwiązaniu TodoGlyphTestnazwę .

  2. Dodaj element projektu Klasyfikator edytora. Aby uzyskać więcej informacji, zobacz Tworzenie rozszerzenia za pomocą szablonu elementu edytora.

  3. Usuń istniejące pliki klas.

Definiowanie glifów

Zdefiniuj glif, uruchamiając IGlyphFactory interfejs.

Aby zdefiniować glif

  1. Dodaj plik klasy i nadaj mu TodoGlyphFactorynazwę .

  2. Dodaj następujący kod przy użyciu deklaracji.

    using System.ComponentModel.Composition;
    using System.Windows;
    using System.Windows.Shapes;
    using System.Windows.Media;
    using System.Windows.Controls;
    using Microsoft.VisualStudio.Text;
    using Microsoft.VisualStudio.Text.Editor;
    using Microsoft.VisualStudio.Text.Formatting;
    using Microsoft.VisualStudio.Text.Tagging;
    using Microsoft.VisualStudio.Utilities;
    
  3. Dodaj klasę o nazwie TodoGlyphFactory , która implementuje IGlyphFactoryelement .

    internal class TodoGlyphFactory : IGlyphFactory
    
  4. Dodaj pole prywatne, które definiuje wymiary glif.

    const double m_glyphSize = 16.0;
    
  5. Zaimplementuj GenerateGlyph , definiując element interfejsu użytkownika (UI). TodoTag program jest zdefiniowany w dalszej części tego przewodnika.

    public UIElement GenerateGlyph(IWpfTextViewLine line, IGlyphTag tag)
    {
        // Ensure we can draw a glyph for this marker.
        if (tag == null || !(tag is TodoTag))
        {
            return null;
        }
    
        System.Windows.Shapes.Ellipse ellipse = new Ellipse();
        ellipse.Fill = Brushes.LightBlue;
        ellipse.StrokeThickness = 2;
        ellipse.Stroke = Brushes.DarkBlue;
        ellipse.Height = m_glyphSize;
        ellipse.Width = m_glyphSize;
    
        return ellipse;
    }
    
  6. Dodaj klasę o nazwie TodoGlyphFactoryProvider , która implementuje IGlyphFactoryProviderelement . Wyeksportuj tę klasę z wartością NameAttribute "TodoGlyph", wartością OrderAttribute After VsTextMarker, znakiem "code" i elementem ContentTypeAttributeTagTypeAttribute TodoTag.

    [Export(typeof(IGlyphFactoryProvider))]
    [Name("TodoGlyph")]
    [Order(After = "VsTextMarker")]
    [ContentType("code")]
    [TagType(typeof(TodoTag))]
    internal sealed class TodoGlyphFactoryProvider : IGlyphFactoryProvider
    
  7. Zaimplementuj metodę GetGlyphFactory , tworząc TodoGlyphFactorywystąpienie klasy .

    public IGlyphFactory GetGlyphFactory(IWpfTextView view, IWpfTextViewMargin margin)
    {
        return new TodoGlyphFactory();
    }
    

Definiowanie tagu zadań do wykonania i sztyletu

Zdefiniuj relację między elementem interfejsu użytkownika zdefiniowanym w poprzednich krokach i marginesem wskaźnika. Utwórz typ tagu i element tagger i wyeksportuj go przy użyciu dostawcy tagger.

Aby zdefiniować tag zadań do wykonania i sztylet

  1. Dodaj nowy plik klasy do projektu i nadaj mu TodoTaggernazwę .

  2. Dodaj następujące importy.

    using System;
    using System.Collections.Generic;
    using System.ComponentModel.Composition;
    using Microsoft.VisualStudio.Text;
    using Microsoft.VisualStudio.Text.Tagging;
    using Microsoft.VisualStudio.Text.Editor;
    using Microsoft.VisualStudio.Text.Classification;
    using Microsoft.VisualStudio.Utilities;
    
  3. Dodaj klasę o nazwie TodoTag.

    internal class TodoTag : IGlyphTag
    
  4. Zmodyfikuj klasę o nazwie TodoTagger , która implementuje ITagger<T> typ TodoTag.

    internal class TodoTagger : ITagger<TodoTag>
    
  5. TodoTagger W klasie dodaj pola prywatne dla elementu IClassifier i dla tekstu, aby znaleźć je w zakresach klasyfikacji.

    private IClassifier m_classifier;
    private const string m_searchText = "todo";
    
  6. Dodaj konstruktor, który ustawia klasyfikator.

    internal TodoTagger(IClassifier classifier)
    {
        m_classifier = classifier;
    }
    
  7. Zaimplementuj metodę GetTags , wyszukując wszystkie zakresy klasyfikacji, których nazwy zawierają wyraz "komentarz" i którego tekst zawiera tekst wyszukiwania. Za każdym razem, gdy tekst wyszukiwania zostanie znaleziony, wróć do nowego TagSpan<T> typu TodoTag.

    IEnumerable<ITagSpan<TodoTag>> ITagger<TodoTag>.GetTags(NormalizedSnapshotSpanCollection spans)
    {
        foreach (SnapshotSpan span in spans)
        {
            //look at each classification span \
            foreach (ClassificationSpan classification in m_classifier.GetClassificationSpans(span))
            {
                //if the classification is a comment
                if (classification.ClassificationType.Classification.ToLower().Contains("comment"))
                {
                    //if the word "todo" is in the comment,
                    //create a new TodoTag TagSpan
                    int index = classification.Span.GetText().ToLower().IndexOf(m_searchText);
                    if (index != -1)
                    {
                        yield return new TagSpan<TodoTag>(new SnapshotSpan(classification.Span.Start + index, m_searchText.Length), new TodoTag());
                    }
                }
            }
        }
    }
    
  8. Zadeklaruj TagsChanged zdarzenie.

    public event EventHandler<SnapshotSpanEventArgs> TagsChanged;
    
  9. Dodaj klasę o nazwie TodoTaggerProvider , która implementuje ITaggerProviderelement , i wyeksportuj go za pomocą ContentTypeAttribute elementu "code" i elementu TagTypeAttribute TodoTag.

    [Export(typeof(ITaggerProvider))]
    [ContentType("code")]
    [TagType(typeof(TodoTag))]
    class TodoTaggerProvider : ITaggerProvider
    
  10. Zaimportuj plik IClassifierAggregatorService.

    [Import]
    internal IClassifierAggregatorService AggregatorService;
    
  11. Zaimplementuj metodę CreateTagger , tworząc TodoTaggerwystąpienie klasy .

    public ITagger<T> CreateTagger<T>(ITextBuffer buffer) where T : ITag
    {
        if (buffer == null)
        {
            throw new ArgumentNullException("buffer");
        }
    
        return new TodoTagger(AggregatorService.GetClassifier(buffer)) as ITagger<T>;
    }
    

Kompilowanie i testowanie kodu

Aby przetestować ten kod, skompiluj rozwiązanie TodoGlyphTest i uruchom je w wystąpieniu eksperymentalnym.

Aby skompilować i przetestować rozwiązanie TodoGlyphTest

  1. Stwórz rozwiązanie.

  2. Uruchom projekt, naciskając klawisz F5. Zostanie uruchomione drugie wystąpienie programu Visual Studio.

  3. Upewnij się, że margines wskaźnika jest wyświetlany. (Na stronie Menu Narzędzia , kliknij pozycję Opcje. Na stronie Edytor tekstów upewnij się, że wybrano margines wskaźnika).

  4. Otwórz plik kodu zawierający komentarze. Dodaj słowo "todo" do jednej z sekcji komentarzy.

  5. Jasnoniebieski okrąg z ciemnoniebieskim konturem pojawia się na marginesie wskaźnika po lewej stronie okna kodu.