2

How can I modify this sample: https://msdn.microsoft.com/en-us/library/ee361745.aspx to have glyphs added to the margin when a button I added is clicked?

I have a button which creates a special kind of breakpoint. I would like this kind to be recognized by my own margin glyph. So I wrote the GetTags method in my Tagger class as follows:

    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());
                    }
                }
            }
        }
    }

However, glyphs are added after moving the cursor to a different line of code or making changes to the code. What do I have to do to have glyphs added right after the button is clicked?

Jakub Bielawa
  • 144
  • 2
  • 8

2 Answers2

2

GetTags is called by the editor whenever a layout happens, but the editor won't call it for any random reason. (Think: how would it know when to call you?) You need to raise the TagsChanged event from your tagger to say the tags for a given span changed, and then it'll call GetTags again to refresh.

As an unrelated piece of advice: you shouldn't be using DTE.ActiveDocument in your GetTags for a few reasons:

  1. GetTags should be as fast as possible...calling DTE methods are rarely fast.
  2. Imagine you have two files open, and GetTags is called for the non-active file. That would have both files looking at the same filename which is probably bad. There's code here that shows how to fetch the file name from an ITextBuffer.
Jason Malinowski
  • 18,148
  • 1
  • 38
  • 55
  • 1
    What works perfectly? This is marked as the answer, but the goal was to determine how to raise the TagsChanged event from a tool window button click (for example). I am reading this and I still have no idea how to accomplish that. If the user clicks a button, HOW do you trigger and raise the TagsChanged event so the glyphs are refreshed? – sthede Apr 27 '16 at 15:30
  • Is there a way to raise a TagsChanged event from menu command. I want to update the textview tags after a process finished. Thank you. – madufit1 May 17 '17 at 17:57
  • 1
    @madufit1 In a nutshell, you have some way to find your tagger and then have it raise tags changed. You should ask a new question on StackOverflow with further details, as comments here aren't big enough to properly answer it. – Jason Malinowski May 22 '17 at 04:27
  • @JasonMalinowski thank you very much for your reply. There are few question raised and still unanswered in the stackoverflow regarding this issue. For example : http://stackoverflow.com/questions/36760891/visual-studio-mef-extension-force-margin-glyphs-to-be-updated-or-redraw?rq=1 – madufit1 May 22 '17 at 08:11
  • I'll add a new question after doing more research on the issue. – madufit1 May 22 '17 at 09:38
0

This is copied from my answer 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 example to make these changes.

Using the IViewTaggerProvider, you can then call

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

in your functions to explicitly call GetTags and go over the spans in the current snapshot.

nicooo21
  • 158
  • 8