Visual Studio SDK - 如何在调用的命令上添加边距字形?

Visual Studio SDK - How to add a margin glyph on command invoked?

我如何修改此示例:https://msdn.microsoft.com/en-us/library/ee361745.aspx 以在单击我添加的按钮时将字形添加到页边距?

我有一个按钮可以创建一种特殊的断点。我希望这种被我自己的边距字形识别。所以我在我的Taggerclass中写了GetTags方法如下:

    IEnumerable<ITagSpan<MyBreakpointTag>> ITagger<MyBreakpointTag>.GetTags(NormalizedSnapshotSpanCollection spans)
    {
        if (BreakpointManager != null)
        {
            DTE2 ide = ServiceProvider.GlobalProvider.GetService(typeof(DTE)) as DTE2;
            Document document = ide.ActiveDocument;

            foreach (SnapshotSpan span in spans)
            {
                ITextSnapshot textSnapshot = span.Snapshot;
                foreach (ITextSnapshotLine textSnapshotLine in textSnapshot.Lines)
                {
                    if (BreakpointManager.IsMyBreakpointAt(document.FullName, textSnapshotLine.LineNumber + 1))
                    {
                        yield return new TagSpan<MyBreakpointTag>(new SnapshotSpan(textSnapshotLine.Start, 1),
                                new MyBreakpointTag());
                    }
                }
            }
        }
    }

但是,将光标移动到不同的代码行或更改代码后会添加字形。我需要做什么才能在单击按钮后立即添加字形?

每当布局发生时编辑器都会调用GetTags,但编辑器不会出于任何随机原因调用它。 (想一想:它怎么知道什么时候给你打电话?)你需要从你的标记器中引发 TagsChanged 事件来说明给定跨度的标签发生了变化,然后它会再次调用 GetTags 来刷新。

一条不相关的建议:出于以下几个原因,您不应该在 GetTags 中使用 DTE.ActiveDocument:

  1. GetTags 应该尽可能快...调用 DTE 方法很少很快。
  2. 假设您打开了两个文件,并且为非活动文件调用了 GetTags。这将使 两个 文件查看相同的文件名,这可能是错误的。有代码 here 展示了如何从 ITextBuffer 中获取文件名。

这是从我的回答 here. Basically, changing from using ITaggerProvider to IViewTaggerProvider allowed me to redraw the glyphs. I used the Implementing a Brace Matching Tagger Provider section in Walkthrough: Displaying Matching Braces 示例中复制的,以进行这些更改。

使用 IViewTaggerProvider,您可以调用

TagsChanged?.Invoke(this, new SnapshotSpanEventArgs(
                              new SnapshotSpan(
                                      SourceBuffer.CurrentSnapshot,
                                      0, 
                                      SourceBuffer.CurrentSnapshot.Length)));

在您的函数中显式调用 GetTags 并遍历当前快照中的跨度。