Compartir vía


Tutorial: Creación de un glifo de margen

Puede personalizar la apariencia de los márgenes del editor mediante extensiones de editor personalizadas. En este tutorial se coloca un glifo personalizado en el margen del indicador cada vez que la palabra "todo" aparece en un comentario de código.

Creación de un proyecto MEF

  1. Cree un proyecto VSIX de C#. (En Cuadro de diálogo Nuevo proyecto , seleccione Visual C# / Extensibilidad y, después , Proyecto VSIX). Asigne un nombre a la solución TodoGlyphTest.

  2. Agregue un elemento de proyecto Clasificador del editor. Para obtener más información, vea Creación de una extensión con una plantilla de elemento de editor.

  3. Elimine los archivos de clase existentes.

Definir el glifo

Defina un glifo ejecutando la IGlyphFactory interfaz .

Para definir el glifo

  1. Agregue un archivo de clase y asígnele el nombre TodoGlyphFactory.

  2. Agregue el código siguiente mediante declaraciones.

    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. Agregue una clase denominada TodoGlyphFactory que implemente IGlyphFactory.

    internal class TodoGlyphFactory : IGlyphFactory
    
  4. Agregue un campo privado que defina las dimensiones del glifo.

    const double m_glyphSize = 16.0;
    
  5. Implemente GenerateGlyph definiendo el elemento de interfaz de usuario (UI) glifo. TodoTag se define más adelante en este tutorial.

    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. Agregue una clase denominada TodoGlyphFactoryProvider que implemente IGlyphFactoryProvider. Exporte esta clase con un NameAttribute de "TodoGlyph", un OrderAttribute de After VsTextMarker, un ContentTypeAttribute de "code" y un TagTypeAttribute de TodoTag.

    [Export(typeof(IGlyphFactoryProvider))]
    [Name("TodoGlyph")]
    [Order(After = "VsTextMarker")]
    [ContentType("code")]
    [TagType(typeof(TodoTag))]
    internal sealed class TodoGlyphFactoryProvider : IGlyphFactoryProvider
    
  7. Implemente el método mediante la GetGlyphFactory creación de instancias de TodoGlyphFactory.

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

Definición de una etiqueta y un tagger de tareas pendientes

Defina la relación entre el elemento de interfaz de usuario que definió en los pasos anteriores y el margen del indicador. Cree un tipo de etiqueta y un tagger y expórtelo mediante un proveedor de etiquetas.

Para definir una etiqueta de tareas pendientes y un tagger

  1. Agregue un nuevo archivo de clase al proyecto y asígnele TodoTaggerel nombre .

  2. Agregue las importaciones siguientes.

    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. Agregue una clase denominada TodoTag.

    internal class TodoTag : IGlyphTag
    
  4. Modifique la clase denominada TodoTagger que implementa ITagger<T> de tipo TodoTag.

    internal class TodoTagger : ITagger<TodoTag>
    
  5. En la TodoTagger clase , agregue campos privados para y IClassifier para que el texto se busque en los intervalos de clasificación.

    private IClassifier m_classifier;
    private const string m_searchText = "todo";
    
  6. Agregue un constructor que establezca el clasificador.

    internal TodoTagger(IClassifier classifier)
    {
        m_classifier = classifier;
    }
    
  7. Implemente el GetTags método buscando todos los intervalos de clasificación cuyos nombres incluyen la palabra "comentario" y cuyo texto incluye el texto de búsqueda. Siempre que se encuentre el texto de búsqueda, devuelva un nuevo 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. Declare un TagsChanged evento.

    public event EventHandler<SnapshotSpanEventArgs> TagsChanged;
    
  9. Agregue una clase denominada TodoTaggerProvider que implemente ITaggerProvidery expórtela con un ContentTypeAttribute de "código" y un TagTypeAttribute de TodoTag.

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

    [Import]
    internal IClassifierAggregatorService AggregatorService;
    
  11. Implemente el método mediante la CreateTagger creación de instancias de 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>;
    }
    

Compilación y prueba del código

Para probar este código, compile la solución TodoGlyphTest y ejecútelo en la instancia experimental.

Para compilar y probar la solución TodoGlyphTest

  1. Compile la solución.

  2. Ejecute el proyecto presionando F5. Se inicia una segunda instancia de Visual Studio.

  3. Asegúrese de que se muestra el margen del indicador. (En el Menú Herramientas , haga clic en Opciones. En la página Editor de texto, asegúrese de que el margen indicador está seleccionado).

  4. Abra un archivo de código que tenga comentarios. Agregue la palabra "todo" a una de las secciones de comentarios.

  5. Un círculo azul claro con un contorno azul oscuro aparece en el margen del indicador a la izquierda de la ventana de código.