Compartir a través de


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 el cuadro de diálogo Nuevo proyecto , seleccione Visual C# / Extensibilidad y, a continuación, 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 Crear 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 TodoGlyphFactoryel nombre .

  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 que representa el 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 al instanciar TodoGlyphFactory.

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

Definir una etiqueta Todo 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 etiquetador

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

  2. Agregue las siguientes importaciones.

    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 clase TodoTagger, agregue campos privados para un IClassifier y para el texto a buscar en las extensiones 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, retorne un nuevo TagSpan<T> del 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. Declarar 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 instanciando 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 panel Opciones>de herramientas, en la sección De toda la configuración>Editor de texto>General>Visualización, confirme que la casilla Mostrar margen del indicador está activada.

    En el cuadro de diálogo Opciones de herramientas>, en la secciónPresentacióngeneral> del Editor> de texto, confirme que la casilla Margen de indicador está activada.

  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.