可以使用自定义编辑器扩展自定义编辑器边距的外观。 每当代码注释中出现“todo”一词时,本演练都会将自定义标志符号放在指示器边距上。
创建 MEF 项目
- 创建 C# VSIX 项目。 (在 “新建项目 ”对话框,选择 Visual C# /扩展性,然后选择 VSIX Project。)将解决方案 - TodoGlyphTest命名为 。
 
- 添加编辑器分类器项目项。 有关详细信息,请参阅使用编辑器项模板创建扩展。 
- 删除现有的类文件。 
定义字形
通过运行 IGlyphFactory 接口来定义字形。
定义字形
- 添加一个类文件并将其命名为 - TodoGlyphFactory。
 
- 使用声明添加以下代码。 - 
- 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;
 - Imports System.ComponentModel.Composition
Imports System.Windows
Imports System.Windows.Shapes
Imports System.Windows.Media
Imports System.Windows.Controls
Imports Microsoft.VisualStudio.Text
Imports Microsoft.VisualStudio.Text.Editor
Imports Microsoft.VisualStudio.Text.Formatting
Imports Microsoft.VisualStudio.Text.Tagging
Imports Microsoft.VisualStudio.Utilities
 
 
- 添加一个名为 - TodoGlyphFactory实现的 IGlyphFactory类。
 - 
- internal class TodoGlyphFactory : IGlyphFactory
 - Friend Class TodoGlyphFactory
    Implements IGlyphFactory
 
 
- 添加一个专用字段,用于定义字形的尺寸。 - 
- const double m_glyphSize = 16.0;
 - Const m_glyphSize As Double = 16.0
 
 
- 通过定义字形用户界面 (UI) 元素来实现 - GenerateGlyph。- TodoTag在本演练的后面部分定义。
 - 
- 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;
}
 - Public Function GenerateGlyph(ByVal line As IWpfTextViewLine, ByVal tag As IGlyphTag) As System.Windows.UIElement Implements IGlyphFactory.GenerateGlyph
    ' Ensure we can draw a glyph for this marker.
    If tag Is Nothing OrElse Not (TypeOf tag Is TodoTag) Then
        Return Nothing
    End If
    Dim ellipse As Ellipse = New Ellipse()
    ellipse.Fill = Brushes.LightBlue
    ellipse.StrokeThickness = 2
    ellipse.Stroke = Brushes.DarkBlue
    ellipse.Height = m_glyphSize
    ellipse.Width = m_glyphSize
    Return ellipse
End Function
 
 
- 添加一个名为 - TodoGlyphFactoryProvider实现的 IGlyphFactoryProvider类。 使用NameAttribute“TodoGlyph”、After VsTextMarkerContentTypeAttribute、OrderAttribute“code”和 TagTypeAttribute TodoTag 的类导出。
 - 
- [Export(typeof(IGlyphFactoryProvider))]
[Name("TodoGlyph")]
[Order(After = "VsTextMarker")]
[ContentType("code")]
[TagType(typeof(TodoTag))]
internal sealed class TodoGlyphFactoryProvider : IGlyphFactoryProvider
 - <Export(GetType(IGlyphFactoryProvider)), Name("TodoGlyph"), Order(After:="VsTextMarker"), ContentType("code"), TagType(GetType(TodoTag))>
Friend NotInheritable Class TodoGlyphFactoryProvider
    Implements IGlyphFactoryProvider
 
 
- GetGlyphFactory通过实例化- TodoGlyphFactory方法实现该方法。
 - 
- public IGlyphFactory GetGlyphFactory(IWpfTextView view, IWpfTextViewMargin margin)
{
    return new TodoGlyphFactory();
}
 - Public Function GetGlyphFactory(ByVal view As IWpfTextView, ByVal margin As IWpfTextViewMargin) As IGlyphFactory Implements IGlyphFactoryProvider.GetGlyphFactory
    Return New TodoGlyphFactory()
End Function
 
 
定义 Todo 标记和标记器
定义在前面的步骤中定义的 UI 元素与指示器边距之间的关系。 使用标记器提供程序创建标记类型和标记器并将其导出。
定义待办事项标记和标记器
- 向项目添加新类文件并将其命名 - TodoTagger。
 
- 添加以下 import 语句。 - 
- 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;
 - Imports System
Imports System.Collections.Generic
Imports System.ComponentModel.Composition
Imports Microsoft.VisualStudio.Text
Imports Microsoft.VisualStudio.Text.Tagging
Imports Microsoft.VisualStudio.Text.Editor
Imports Microsoft.VisualStudio.Text.Classification
Imports Microsoft.VisualStudio.Utilities
 
 
- 添加名为的 - TodoTag的类。
 - 
- internal class TodoTag : IGlyphTag
 - Friend Class TodoTag
    Implements IGlyphTag
    Public Sub New()
        MyBase.New()
    End Sub
End Class
 
 
- 修改名为 - TodoTagger实现 ITagger<T> 类型的- TodoTag类。
 - 
- internal class TodoTagger : ITagger<TodoTag>
 - Friend Class TodoTagger
    Implements ITagger(Of TodoTag)
 
 
- 在类中 - TodoTagger,为一个 IClassifier 和文本添加专用字段,以便在分类范围中找到这些字段。
 - 
- private IClassifier m_classifier;
private const string m_searchText = "todo";
 - Private m_classifier As IClassifier
Private Const m_searchText As String = "todo"
 
 
- 添加设置分类器的构造函数。 - 
- internal TodoTagger(IClassifier classifier)
{
    m_classifier = classifier;
}
 - Friend Sub New(ByVal classifier As IClassifier)
    m_classifier = classifier
End Sub
 
 
- GetTags通过查找名称包括单词“comment”且其文本包括搜索文本的所有分类范围来实现该方法。 只要找到搜索文本,请返回新 TagSpan<T> 类型 - 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());
                }
            }
        }
    }
}
 - Private Function GetTags(ByVal spans As NormalizedSnapshotSpanCollection) As IEnumerable(Of ITagSpan(Of TodoTag)) Implements ITagger(Of TodoTag).GetTags
    Dim list As List(Of ITagSpan(Of TodoTag))
    list = New List(Of ITagSpan(Of TodoTag))()
    For Each span As SnapshotSpan In spans
        'look at each classification span \
        For Each classification As ClassificationSpan In m_classifier.GetClassificationSpans(span)
            'if the classification is a comment
            If classification.ClassificationType.Classification.ToLower().Contains("comment") Then
                'if the word "todo" is in the comment,
                'create a new TodoTag TagSpan
                Dim index As Integer = classification.Span.GetText().ToLower().IndexOf(m_searchText)
                If index <> -1 Then
                    list.Add(New TagSpan(Of TodoTag)(New SnapshotSpan(classification.Span.Start + index, m_searchText.Length), New TodoTag()))
                End If
            End If
        Next classification
    Next span
    Return list
End Function
 
 
- 声明事件 - TagsChanged。
 - 
- public event EventHandler<SnapshotSpanEventArgs> TagsChanged;
 - Public Event TagsChanged(ByVal sender As Object, ByVal e As Microsoft.VisualStudio.Text.SnapshotSpanEventArgs) Implements Microsoft.VisualStudio.Text.Tagging.ITagger(Of TodoTag).TagsChanged
 
 
- 添加一个名为- TodoTaggerProvider实现ITaggerProvider的类,并使用“代码”和 TagTypeAttribute TodoTag 导出它ContentTypeAttribute。
 - 
- [Export(typeof(ITaggerProvider))]
[ContentType("code")]
[TagType(typeof(TodoTag))]
class TodoTaggerProvider : ITaggerProvider
 - <Export(GetType(ITaggerProvider)), ContentType("code"), TagType(GetType(TodoTag))>
Friend Class TodoTaggerProvider
    Implements ITaggerProvider
 
 
- 导入 IClassifierAggregatorService。 - 
- [Import]
internal IClassifierAggregatorService AggregatorService;
 - <Import()>
Friend AggregatorService As IClassifierAggregatorService
 
 
- CreateTagger通过实例化- 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>;
}
 - Public Function CreateTagger(Of T As Microsoft.VisualStudio.Text.Tagging.ITag)(ByVal buffer As Microsoft.VisualStudio.Text.ITextBuffer) As Microsoft.VisualStudio.Text.Tagging.ITagger(Of T) Implements Microsoft.VisualStudio.Text.Tagging.ITaggerProvider.CreateTagger
    If buffer Is Nothing Then
        Throw New ArgumentNullException("buffer")
    End If
    Return TryCast(New TodoTagger(AggregatorService.GetClassifier(buffer)), ITagger(Of T))
End Function
 
 
生成并测试代码
若要测试此代码,请生成 TodoGlyphTest 解决方案并在实验实例中运行它。
生成和测试 TodoGlyphTest 解决方案
- 生成解决方案。 
- 按 F5 运行项目。 Visual Studio 的第二个实例启动。 
- 确保显示指示器边距。 (On the 工具 菜单,单击“ 选项”。在 “文本编辑器” 页上,确保 已选择指示器边距 。 
- 打开包含注释的代码文件。 将“todo”一词添加到注释部分之一。 
- 带有深蓝色轮廓的浅蓝色圆圈显示在代码窗口左侧的指示器边距中。