Procedura dettagliata: Creare un glifo del margine

È possibile personalizzare l'aspetto dei margini dell'editor usando estensioni dell'editor personalizzate. Questa procedura dettagliata inserisce un glifo personalizzato sul margine dell'indicatore ogni volta che la parola "todo" viene visualizzata in un commento di codice.

Creare un progetto MEF

  1. Creare un progetto VSIX C#. (In Finestra di dialogo Nuovo progetto , selezionare Visual C# / Estendibilità e quindi progetto VSIX. Assegnare alla soluzione TodoGlyphTestil nome .

  2. Aggiungere un elemento di progetto Classificatore editor. Per altre informazioni, vedere Creare un'estensione con un modello di elemento dell'editor.

  3. Eliminare i file di classe esistenti.

Definire il glifo

Definire un glifo eseguendo l'interfaccia IGlyphFactory .

Per definire il glifo

  1. Aggiungere un file di classe e assegnargli il nome TodoGlyphFactory.

  2. Aggiungere il codice seguente usando le dichiarazioni.

    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. Aggiungere una classe denominata TodoGlyphFactory che implementa IGlyphFactory.

    internal class TodoGlyphFactory : IGlyphFactory
    
  4. Aggiungere un campo privato che definisce le dimensioni del glifo.

    const double m_glyphSize = 16.0;
    
  5. Implementare GenerateGlyph definendo l'elemento dell'interfaccia utente del glifo. TodoTag viene definito più avanti in questa procedura dettagliata.

    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. Aggiungere una classe denominata TodoGlyphFactoryProvider che implementa IGlyphFactoryProvider. Esportare questa classe con un NameAttribute valore di "TodoGlyph", di OrderAttribute After VsTextMarker, di ContentTypeAttribute "codice" e di TagTypeAttribute TodoTag.

    [Export(typeof(IGlyphFactoryProvider))]
    [Name("TodoGlyph")]
    [Order(After = "VsTextMarker")]
    [ContentType("code")]
    [TagType(typeof(TodoTag))]
    internal sealed class TodoGlyphFactoryProvider : IGlyphFactoryProvider
    
  7. Implementare il GetGlyphFactory metodo creando un'istanza di TodoGlyphFactory.

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

Definire un tag Todo e un tagger

Definire la relazione tra l'elemento dell'interfaccia utente definito nei passaggi precedenti e il margine dell'indicatore. Creare un tipo di tag e contrassegnarlo ed esportarlo usando un provider di tagger.

Per definire un tag todo e un tagger

  1. Aggiungere un nuovo file di classe al progetto e denominarlo TodoTagger.

  2. Aggiungere le importazioni seguenti.

    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. Aggiungere una classe denominata TodoTag.

    internal class TodoTag : IGlyphTag
    
  4. Modificare la classe denominata TodoTagger che implementa ITagger<T> il tipo TodoTag.

    internal class TodoTagger : ITagger<TodoTag>
    
  5. Per la TodoTagger classe aggiungere campi privati per un oggetto IClassifier e per il testo da trovare negli intervalli di classificazione.

    private IClassifier m_classifier;
    private const string m_searchText = "todo";
    
  6. Aggiungere un costruttore che imposta il classificatore.

    internal TodoTagger(IClassifier classifier)
    {
        m_classifier = classifier;
    }
    
  7. Implementare il GetTags metodo trovando tutti gli intervalli di classificazione i cui nomi includono la parola "commento" e il cui testo include il testo di ricerca. Ogni volta che viene trovato il testo di ricerca, restituire un nuovo TagSpan<T> tipo 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. Dichiarare un TagsChanged evento.

    public event EventHandler<SnapshotSpanEventArgs> TagsChanged;
    
  9. Aggiungere una classe denominata TodoTaggerProvider che implementa ITaggerProvidered esportarla con un ContentTypeAttribute di "codice" e un TagTypeAttribute di TodoTag.

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

    [Import]
    internal IClassifierAggregatorService AggregatorService;
    
  11. Implementare il CreateTagger metodo creando un'istanza di TodoTagger.

    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>;
    }
    

Compilare e testare il codice

Per testare questo codice, compilare la soluzione TodoGlyphTest ed eseguirla nell'istanza sperimentale.

Per compilare e testare la soluzione TodoGlyphTest

  1. Compilare la soluzione.

  2. Eseguire il progetto premendo F5. Viene avviata una seconda istanza di Visual Studio.

  3. Assicurarsi che il margine dell'indicatore sia visualizzato. (In Scegliere Opzioni dal menu Strumenti. Nella pagina Editor di testo verificare che sia selezionato Margine indicatore.

  4. Aprire un file di codice con commenti. Aggiungere la parola "todo" a una delle sezioni di commento.

  5. Un cerchio blu chiaro con un contorno blu scuro viene visualizzato nel margine dell'indicatore a sinistra della finestra del codice.