可以使用自定义编辑器扩展自定义编辑器边距的外观。 每当代码注释中出现“todo”一词时,本演示都会将自定义符号放在指示器的边距上。
创建 MEF 项目
创建 C# VSIX 项目。 (在 “新建项目 ”对话框中,选择 Visual C# /Extensibility,然后选择 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 VsTextMarkerOrderAttribute、ContentTypeAttribute“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
通过实例化TodoGlyphFactory来实现GetGlyphFactory方法。
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。
添加以下导入。
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
通过查找名称包含“comment”且文本包含搜索文本的所有分类范围来实现GetTags方法。 当找到搜索文本时,生成一个新的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,并使用ContentTypeAttribute代码和TagTypeAttribute TodoTag导出它。
[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
通过实例化TodoTagger来实现CreateTagger方法。
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 的第二个实例启动。
确保指示器边距可见。
在 “工具>选项 ”窗格中的“ 所有设置>文本编辑器>常规>显示 ”部分下,确认已选中“ 显示指示器边距 ”复选框。
在 “工具>选项 ”对话框中,在 “文本编辑器>常规>显示 ”部分下,确认选中了 “指示器边距 ”复选框。
打开包含注释的代码文件。 将“todo”一词添加到一个注释区。
带有深蓝色轮廓的浅蓝色圆圈显示在代码窗口左侧的指示器边距中。