Condividi tramite


procedura dettagliata: Evidenziazione del testo

È possibile aggiungere effetti visivi diversi editor tramite gli elementi del Framework (MEF) di estensibilità gestito. In questa procedura dettagliata viene illustrato come evidenziare tutte le occorrenze di una parola corrente in un file di testo. Se una parola si verifica più volte in un file di testo e inserire il cursore in una occorrenza, ogni occorrenza viene evidenziata.

Prerequisiti

Per completare questa procedura dettagliata, è necessario installare Visual Studio 2010 SDK.

Nota

per ulteriori informazioni su Visual Studio SDK, vedere Cenni preliminari sull'estensione di Visual Studio.Per ulteriori informazioni su come scaricare Visual Studio SDK, vedere Centro per sviluppatori di estensibilità di Visual Studio il sito Web MSDN.

Creare un progetto MEF

Per creare un progetto MEF

  1. Creare un progetto di classificatore editor. Assegnare alla soluzione HighlightWordTest.

  2. Aprire il file source.extension.vsixmanifest nell'editor del manifesto VSIX.

  3. Assicurarsi che la direzione di Content contenga un tipo di contenuto componente MEF e che Path è impostato su HighlightWordTest.dll.

  4. salvare e chiudere source.extension.vsixmanifest.

  5. Eliminare i file di classe esistenti.

Definizione di TextMarkerTag

Il primo passaggio di testo di evidenziazione è la sottoclasse TextMarkerTag e definisce l'aspetto.

Per definire un TextMarkerTag e un MarkerFormatDefinition

  1. Aggiungere il file di classe e denominarlo HighlightWordTag.

  2. Includere gli spazi dei nomi seguenti.

    Imports System
    Imports System.Collections.Generic
    Imports System.ComponentModel.Composition
    Imports System.Linq
    Imports System.Threading
    Imports System.Windows.Media
    Imports Microsoft.VisualStudio.Text
    Imports Microsoft.VisualStudio.Text.Classification
    Imports Microsoft.VisualStudio.Text.Editor
    Imports Microsoft.VisualStudio.Text.Operations
    Imports Microsoft.VisualStudio.Text.Tagging
    Imports Microsoft.VisualStudio.Utilities
    
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.Composition;
    using System.Linq;
    using System.Threading;
    using System.Windows.Media;
    using Microsoft.VisualStudio.Text;
    using Microsoft.VisualStudio.Text.Classification;
    using Microsoft.VisualStudio.Text.Editor;
    using Microsoft.VisualStudio.Text.Operations;
    using Microsoft.VisualStudio.Text.Tagging;
    using Microsoft.VisualStudio.Utilities;
    
  3. Creare una classe che eredita da TextMarkerTag e denominarla HighlightWordTag.

    Friend Class HighlightWordTag
        Inherits TextMarkerTag
    
    internal class HighlightWordTag : TextMarkerTag
    
  4. Creare un'altra classe che eredita da MarkerFormatDefinitione denominarla HighlightWordFormatDefinition. Per utilizzare questa definizione di formato per il tag, è necessario esportarlo con gli attributi seguenti:

    • NameAttribute: i tag utilizzano questo per fare riferimento a questo formato

    • UserVisibleAttribute: in questo modo il formato a visualizzato nell'interfaccia utente

    <Export(GetType(EditorFormatDefinition))>
    <Name("MarkerFormatDefinition/HighlightWordFormatDefinition")>
    <UserVisible(True)>
    Friend Class HighlightWordFormatDefinition
        Inherits MarkerFormatDefinition
    
    [Export(typeof(EditorFormatDefinition))]
    [Name("MarkerFormatDefinition/HighlightWordFormatDefinition")]
    [UserVisible(true)]
    internal class HighlightWordFormatDefinition : MarkerFormatDefinition
    
  5. Nel costruttore per HighlightWordFormatDefinition, definirne il nome visualizzato e l'aspetto. La proprietà background definisce il colore di riempimento, mentre la proprietà del primo piano definisce il colore del bordo.

    Public Sub New()
        Me.BackgroundColor = Colors.LightBlue
        Me.ForegroundColor = Colors.DarkBlue
        Me.DisplayName = "Highlight Word" 
        Me.ZOrder = 5
    End Sub
    
    public HighlightWordFormatDefinition()
    {
        this.BackgroundColor = Colors.LightBlue;
        this.ForegroundColor = Colors.DarkBlue;
        this.DisplayName = "Highlight Word";
        this.ZOrder = 5;
    }
    
  6. Nel costruttore per HighlightWordTag, passare il nome della definizione di formato appena creata.

    Public Sub New()
        MyBase.New("MarkerFormatDefinition/HighlightWordFormatDefinition")
    End Sub
    
    public HighlightWordTag() : base("MarkerFormatDefinition/HighlightWordFormatDefinition") { }
    

implementare un ITagger

Il passaggio successivo consiste nell'implementazione di ITagger . Questa interfaccia, assegna a un buffer di testo specificato, i tag che forniscono l'evidenziazione di testo e altri effetti visivi.

Per implementare un tagger

  1. Creare una classe che implementa ITagger di tipo HighlightWordTage denominarla HighlightWordTagger.

    Friend Class HighlightWordTagger
        Implements ITagger(Of HighlightWordTag)
    
    internal class HighlightWordTagger : ITagger<HighlightWordTag>
    
  2. Aggiungere i seguenti campi e proprietà privati nella classe:

    Private _View As ITextView
    Private Property View() As ITextView
        Get 
            Return _View
        End Get 
        Set(ByVal value As ITextView)
            _View = value
        End Set 
    End Property 
    Private _SourceBuffer As ITextBuffer
    Private Property SourceBuffer() As ITextBuffer
        Get 
            Return _SourceBuffer
        End Get 
        Set(ByVal value As ITextBuffer)
            _SourceBuffer = value
        End Set 
    End Property 
    Private _TextSearchService As ITextSearchService
    Private Property TextSearchService() As ITextSearchService
        Get 
            Return _TextSearchService
        End Get 
        Set(ByVal value As ITextSearchService)
            _TextSearchService = value
        End Set 
    End Property 
    Private _TextStructureNavigator As ITextStructureNavigator
    Private Property TextStructureNavigator() As ITextStructureNavigator
        Get 
            Return _TextStructureNavigator
        End Get 
        Set(ByVal value As ITextStructureNavigator)
            _TextStructureNavigator = value
        End Set 
    End Property 
    Private _WordSpans As NormalizedSnapshotSpanCollection
    Private Property WordSpans() As NormalizedSnapshotSpanCollection
        Get 
            Return _WordSpans
        End Get 
        Set(ByVal value As NormalizedSnapshotSpanCollection)
            _WordSpans = value
        End Set 
    End Property 
    Private _CurrentWord As System.Nullable(Of SnapshotSpan)
    Private Property CurrentWord() As System.Nullable(Of SnapshotSpan)
        Get 
            Return _CurrentWord
        End Get 
        Set(ByVal value As System.Nullable(Of SnapshotSpan))
            _CurrentWord = value
        End Set 
    End Property 
    Private _RequestedPoint As SnapshotPoint
    Private Property RequestedPoint() As SnapshotPoint
        Get 
            Return _RequestedPoint
        End Get 
        Set(ByVal value As SnapshotPoint)
            _RequestedPoint = value
        End Set 
    End Property 
    Private updateLock As New Object()
    
    ITextView View { get; set; }
    ITextBuffer SourceBuffer { get; set; }
    ITextSearchService TextSearchService { get; set; }
    ITextStructureNavigator TextStructureNavigator { get; set; }
    NormalizedSnapshotSpanCollection WordSpans { get; set; }
    SnapshotSpan? CurrentWord { get; set; }
    SnapshotPoint RequestedPoint { get; set; }
    object updateLock = new object();
    
  3. Aggiungere un costruttore per inizializzare le proprietà elencate in precedenza e aggiunge LayoutChanged e i gestori eventi di PositionChanged .

    Public Sub New(ByVal view As ITextView, ByVal sourceBuffer As ITextBuffer, ByVal textSearchService As ITextSearchService, ByVal textStructureNavigator As ITextStructureNavigator)
        Me.View = view
        Me.SourceBuffer = sourceBuffer
        Me.TextSearchService = textSearchService
        Me.TextStructureNavigator = textStructureNavigator
        Me.WordSpans = New NormalizedSnapshotSpanCollection()
        Me.CurrentWord = Nothing 
        AddHandler Me.View.Caret.PositionChanged, AddressOf CaretPositionChanged
        AddHandler Me.View.LayoutChanged, AddressOf ViewLayoutChanged
    End Sub
    
    public HighlightWordTagger(ITextView view, ITextBuffer sourceBuffer, ITextSearchService textSearchService,
    ITextStructureNavigator textStructureNavigator)
    {
        this.View = view;
        this.SourceBuffer = sourceBuffer;
        this.TextSearchService = textSearchService;
        this.TextStructureNavigator = textStructureNavigator;
        this.WordSpans = new NormalizedSnapshotSpanCollection();
        this.CurrentWord = null;
        this.View.Caret.PositionChanged += CaretPositionChanged;
        this.View.LayoutChanged += ViewLayoutChanged;
    }
    
  4. I gestori eventi sia chiamano il metodo di UpdateAtCaretPosition .

    Private Sub ViewLayoutChanged(ByVal sender As Object, ByVal e As TextViewLayoutChangedEventArgs)
        ' If a new snapshot wasn't generated, then skip this layout 
        If e.NewSnapshot IsNot e.OldSnapshot Then
            UpdateAtCaretPosition(View.Caret.Position)
        End If 
    End Sub 
    
    Private Sub CaretPositionChanged(ByVal sender As Object, ByVal e As CaretPositionChangedEventArgs)
        UpdateAtCaretPosition(e.NewPosition)
    End Sub
    
    void ViewLayoutChanged(object sender, TextViewLayoutChangedEventArgs e)
    {
        // If a new snapshot wasn't generated, then skip this layout 
        if (e.NewSnapshot != e.OldSnapshot)
        {
            UpdateAtCaretPosition(View.Caret.Position);
        }
    }
    
    void CaretPositionChanged(object sender, CaretPositionChangedEventArgs e)
    {
        UpdateAtCaretPosition(e.NewPosition);
    }
    
  5. È necessario aggiungere anche un evento di TagsChanged che verrà chiamato dal metodo update.

    Public Event TagsChanged(ByVal sender As Object, ByVal e As SnapshotSpanEventArgs) _
        Implements ITagger(Of HighlightWordTag).TagsChanged
    
    public event EventHandler<SnapshotSpanEventArgs> TagsChanged;
    
  6. Il metodo di UpdateAtCaretPosition() cerca ogni parola nel buffer di testo identica alla parola in cui il cursore viene posizionato e viene costruito un elenco con oggetti di SnapshotSpan che corrispondono alle occorrenze di una parola. Chiama quindi SynchronousUpdate, che genera l'evento di TagsChanged .

    Private Sub UpdateAtCaretPosition(ByVal caretPosition As CaretPosition)
        Dim point As System.Nullable(Of SnapshotPoint) = caretPosition.Point.GetPoint(SourceBuffer, caretPosition.Affinity)
    
        If Not point.HasValue Then 
            Exit Sub 
        End If 
    
        ' If the new caret position is still within the current word (and on the same snapshot), we don't need to check it 
        If CurrentWord.HasValue AndAlso CurrentWord.Value.Snapshot Is View.TextSnapshot AndAlso point.Value > CurrentWord.Value.Start AndAlso point.Value < CurrentWord.Value.[End] Then 
            Exit Sub 
        End If
    
        RequestedPoint = point.Value
        UpdateWordAdornments()
    End Sub 
    
    Private Sub UpdateWordAdornments()
        Dim currentRequest As SnapshotPoint = RequestedPoint
        Dim wordSpans As New List(Of SnapshotSpan)()
        'Find all words in the buffer like the one the caret is on 
        Dim word As TextExtent = TextStructureNavigator.GetExtentOfWord(currentRequest)
        Dim foundWord As Boolean = True 
        'If we've selected something not worth highlighting, we might have missed a "word" by a little bit 
        If Not WordExtentIsValid(currentRequest, word) Then 
            'Before we retry, make sure it is worthwhile 
            If word.Span.Start <> currentRequest OrElse currentRequest = currentRequest.GetContainingLine().Start OrElse Char.IsWhiteSpace((currentRequest - 1).GetChar()) Then
                foundWord = False 
            Else 
                ' Try again, one character previous.  
                'If the caret is at the end of a word, pick up the word.
                word = TextStructureNavigator.GetExtentOfWord(currentRequest - 1)
    
                'If the word still isn't valid, we're done 
                If Not WordExtentIsValid(currentRequest, word) Then
                    foundWord = False 
                End If 
            End If 
        End If 
    
        If Not foundWord Then 
            'If we couldn't find a word, clear out the existing markers
            SynchronousUpdate(currentRequest, New NormalizedSnapshotSpanCollection(), Nothing)
            Exit Sub 
        End If 
    
        Dim currentWord__1 As SnapshotSpan = word.Span
        'If this is the current word, and the caret moved within a word, we're done. 
        If CurrentWord.HasValue AndAlso currentWord__1 = CurrentWord Then 
            Exit Sub 
        End If 
    
        'Find the new spans 
        Dim findData As New FindData(currentWord__1.GetText(), currentWord__1.Snapshot)
        findData.FindOptions = FindOptions.WholeWord Or FindOptions.MatchCase
    
        wordSpans.AddRange(TextSearchService.FindAll(findData))
    
        'If another change hasn't happened, do a real update 
        If currentRequest = RequestedPoint Then
            SynchronousUpdate(currentRequest, New NormalizedSnapshotSpanCollection(wordSpans), currentWord__1)
        End If 
    End Sub 
    Private Shared Function WordExtentIsValid(ByVal currentRequest As SnapshotPoint, ByVal word As TextExtent) As Boolean 
        Return word.IsSignificant AndAlso currentRequest.Snapshot.GetText(word.Span).Any(Function(c) Char.IsLetter(c))
    End Function
    
    void UpdateAtCaretPosition(CaretPosition caretPosition)
    {
        SnapshotPoint? point = caretPosition.Point.GetPoint(SourceBuffer, caretPosition.Affinity);
    
        if (!point.HasValue)
            return;
    
        // If the new caret position is still within the current word (and on the same snapshot), we don't need to check it 
        if (CurrentWord.HasValue
            && CurrentWord.Value.Snapshot == View.TextSnapshot
            && point.Value >= CurrentWord.Value.Start
            && point.Value <= CurrentWord.Value.End)
        {
            return;
        }
    
        RequestedPoint = point.Value;
        UpdateWordAdornments();
    }
    
    void UpdateWordAdornments()
    {
        SnapshotPoint currentRequest = RequestedPoint;
        List<SnapshotSpan> wordSpans = new List<SnapshotSpan>();
        //Find all words in the buffer like the one the caret is on
        TextExtent word = TextStructureNavigator.GetExtentOfWord(currentRequest);
        bool foundWord = true;
        //If we've selected something not worth highlighting, we might have missed a "word" by a little bit
        if (!WordExtentIsValid(currentRequest, word))
        {
            //Before we retry, make sure it is worthwhile 
            if (word.Span.Start != currentRequest
                 || currentRequest == currentRequest.GetContainingLine().Start
                 || char.IsWhiteSpace((currentRequest - 1).GetChar()))
            {
                foundWord = false;
            }
            else
            {
                // Try again, one character previous.  
                //If the caret is at the end of a word, pick up the word.
                word = TextStructureNavigator.GetExtentOfWord(currentRequest - 1);
    
                //If the word still isn't valid, we're done 
                if (!WordExtentIsValid(currentRequest, word))
                    foundWord = false;
            }
        }
    
        if (!foundWord)
        {
            //If we couldn't find a word, clear out the existing markers
            SynchronousUpdate(currentRequest, new NormalizedSnapshotSpanCollection(), null);
            return;
        }
    
        SnapshotSpan currentWord = word.Span;
        //If this is the current word, and the caret moved within a word, we're done. 
        if (CurrentWord.HasValue && currentWord == CurrentWord)
            return;
    
        //Find the new spans
        FindData findData = new FindData(currentWord.GetText(), currentWord.Snapshot);
        findData.FindOptions = FindOptions.WholeWord | FindOptions.MatchCase;
    
        wordSpans.AddRange(TextSearchService.FindAll(findData));
    
        //If another change hasn't happened, do a real update 
        if (currentRequest == RequestedPoint)
            SynchronousUpdate(currentRequest, new NormalizedSnapshotSpanCollection(wordSpans), currentWord);
    }
    static bool WordExtentIsValid(SnapshotPoint currentRequest, TextExtent word)
    {
        return word.IsSignificant
            && currentRequest.Snapshot.GetText(word.Span).Any(c => char.IsLetter(c));
    }
    
  7. The SynchronousUpdate performs a synchronous update on the WordSpans and CurrentWord properties, and raises the TagsChanged event.

    Private Sub SynchronousUpdate(ByVal currentRequest As SnapshotPoint, ByVal newSpans As NormalizedSnapshotSpanCollection, ByVal newCurrentWord As System.Nullable(Of SnapshotSpan))
        SyncLock updateLock
            If currentRequest <> RequestedPoint Then 
                Exit Sub 
            End If
    
            WordSpans = newSpans
            CurrentWord = newCurrentWord
    
            RaiseEvent TagsChanged(Me, New SnapshotSpanEventArgs(New SnapshotSpan(SourceBuffer.CurrentSnapshot, 0, SourceBuffer.CurrentSnapshot.Length)))
        End SyncLock 
    End Sub
    
    void SynchronousUpdate(SnapshotPoint currentRequest, NormalizedSnapshotSpanCollection newSpans, SnapshotSpan? newCurrentWord)
    {
        lock (updateLock)
        {
            if (currentRequest != RequestedPoint)
                return;
    
            WordSpans = newSpans;
            CurrentWord = newCurrentWord;
    
            var tempEvent = TagsChanged;
            if (tempEvent != null)
                tempEvent(this, new SnapshotSpanEventArgs(new SnapshotSpan(SourceBuffer.CurrentSnapshot, 0, SourceBuffer.CurrentSnapshot.Length)));
        }
    }
    
  8. È necessario implementare il metodo di GetTags . Questo metodo accetta una raccolta di oggetti di SnapshotSpan e restituisce un'enumerazione di intervalli di tag.

    In c#, implementare questo metodo come iteratore delle prestazioni, che consente la valutazione differita ovvero valutazione impostare solo quando i singoli elementi si accede) dei tag. In Visual Basic, aggiungere i tag a un elenco e restituisce l'elenco.

    In questo caso il metodo restituisce un oggetto di TagSpan che ha TextMarkerTag“blue„, che fornisce uno sfondo blu.

    Public Function GetTags(ByVal spans As NormalizedSnapshotSpanCollection) As IEnumerable(Of ITagSpan(Of HighlightWordTag)) Implements ITagger(Of HighlightWordTag).GetTags
        If CurrentWord Is Nothing Then 
            Return Nothing 
            Exit Function 
        End If 
    
        ' Hold on to a "snapshot" of the word spans and current word, so that we maintain the same 
        ' collection throughout 
        Dim currentWord__1 As SnapshotSpan = CurrentWord.Value
        Dim wordSpans__2 As NormalizedSnapshotSpanCollection = WordSpans
    
        If spans.Count = 0 OrElse WordSpans.Count = 0 Then 
            Return Nothing 
            Exit Function 
        End If 
    
        ' If the requested snapshot isn't the same as the one our words are on, translate our spans to the expected snapshot 
        If spans(0).Snapshot IsNot wordSpans__2(0).Snapshot Then
            wordSpans__2 = New NormalizedSnapshotSpanCollection(wordSpans__2.[Select](Function(span) span.TranslateTo(spans(0).Snapshot, SpanTrackingMode.EdgeExclusive)))
    
            currentWord__1 = currentWord__1.TranslateTo(spans(0).Snapshot, SpanTrackingMode.EdgeExclusive)
        End If 
        'in order to emulate the C# yield return functionality, 
        'create a list and add all the relevant spans to it, then return the list 
        Dim list As List(Of TagSpan(Of HighlightWordTag))
        list = New List(Of TagSpan(Of HighlightWordTag))()
    
        If spans.OverlapsWith(New NormalizedSnapshotSpanCollection(currentWord__1)) Then
            list.Add(New TagSpan(Of HighlightWordTag)(CurrentWord, New HighlightWordTag()))
        End If 
    
        For Each span As SnapshotSpan In NormalizedSnapshotSpanCollection.Overlap(spans, wordSpans__2)
            list.Add(New TagSpan(Of HighlightWordTag)(span, New HighlightWordTag()))
        Next 
        Return List
    End Function
    
    public IEnumerable<ITagSpan<HighlightWordTag>> GetTags(NormalizedSnapshotSpanCollection spans)
    {
        if (CurrentWord == null)
            yield break;
    
        // Hold on to a "snapshot" of the word spans and current word, so that we maintain the same
        // collection throughout
        SnapshotSpan currentWord = CurrentWord.Value;
        NormalizedSnapshotSpanCollection wordSpans = WordSpans;
    
        if (spans.Count == 0 || wordSpans.Count == 0)
            yield break;
    
        // If the requested snapshot isn't the same as the one our words are on, translate our spans to the expected snapshot 
        if (spans[0].Snapshot != wordSpans[0].Snapshot)
        {
            wordSpans = new NormalizedSnapshotSpanCollection(
                wordSpans.Select(span => span.TranslateTo(spans[0].Snapshot, SpanTrackingMode.EdgeExclusive)));
    
            currentWord = currentWord.TranslateTo(spans[0].Snapshot, SpanTrackingMode.EdgeExclusive);
        }
    
        // First, yield back the word the cursor is under (if it overlaps) 
        // Note that we'll yield back the same word again in the wordspans collection; 
        // the duplication here is expected. 
        if (spans.OverlapsWith(new NormalizedSnapshotSpanCollection(currentWord)))
            yield return new TagSpan<HighlightWordTag>(currentWord, new HighlightWordTag());
    
        // Second, yield all the other words in the file 
        foreach (SnapshotSpan span in NormalizedSnapshotSpanCollection.Overlap(spans, wordSpans))
        {
            yield return new TagSpan<HighlightWordTag>(span, new HighlightWordTag());
        }
    }
    

creare un provider di Tagger

Per creare il tagger, è necessario implementare IViewTaggerProvider. Questa classe è un elemento del framework MEF, pertanto è necessario impostare gli attributi corretti in modo da riconoscere questa estensione.

Nota

Per ulteriori informazioni su MEF, vedere Managed Extensibility Framework (MEF).

Per creare un provider di tagger

  1. Creare HighlightWordTaggerProvider classe denominata che implementa IViewTaggerProvidere esportarlo con ContentTypeAttribute di “testo„ e TagTypeAttribute di TextMarkerTag.

    <Export(GetType(IViewTaggerProvider))>
    <ContentType("text")>
    <TagType(GetType(TextMarkerTag))>
    Friend Class HighlightWordTaggerProvider
        Implements IViewTaggerProvider
    
    [Export(typeof(IViewTaggerProvider))]
    [ContentType("text")]
    [TagType(typeof(TextMarkerTag))]
    internal class HighlightWordTaggerProvider : IViewTaggerProvider
    
  2. È necessario includere due servizi dell'editor, ITextSearchService e ITextStructureNavigatorSelectorService, per creare un'istanza del tagger.

    Private _TextSearchService As ITextSearchService
    <Import()> _
    Friend Property TextSearchService() As ITextSearchService
        Get 
            Return _TextSearchService
        End Get 
        Set(ByVal value As ITextSearchService)
            _TextSearchService = value
        End Set 
    End Property 
    
    Private _TextStructureNavigatorSelector As ITextStructureNavigatorSelectorService
    <Import()>
    Friend Property TextStructureNavigatorSelector() As ITextStructureNavigatorSelectorService
        Get 
            Return _TextStructureNavigatorSelector
        End Get 
        Set(ByVal value As ITextStructureNavigatorSelectorService)
            _TextStructureNavigatorSelector = value
        End Set 
    End Property
    
    [Import]
    internal ITextSearchService TextSearchService { get; set; }
    
    [Import]
    internal ITextStructureNavigatorSelectorService TextStructureNavigatorSelector { get; set; }
    
  3. Implementare il metodo di CreateTagger``1 per ottenere un'istanza di HighlightWordTagger.

    Public Function CreateTagger(Of T As ITag)(ByVal textView As ITextView, ByVal buffer As ITextBuffer) As ITagger(Of T) Implements IViewTaggerProvider.CreateTagger
        'provide highlighting only on the top buffer 
        If textView.TextBuffer IsNot buffer Then 
            Return Nothing 
        End If 
    
        Dim textStructureNavigator As ITextStructureNavigator = TextStructureNavigatorSelector.GetTextStructureNavigator(buffer)
    
        Return TryCast(New HighlightWordTagger(textView, buffer, TextSearchService, textStructureNavigator), ITagger(Of T))
    End Function
    
    public ITagger<T> CreateTagger<T>(ITextView textView, ITextBuffer buffer) where T : ITag
    {
        //provide highlighting only on the top buffer 
        if (textView.TextBuffer != buffer)
            return null;
    
        ITextStructureNavigator textStructureNavigator =
            TextStructureNavigatorSelector.GetTextStructureNavigator(buffer);
    
        return new HighlightWordTagger(textView, buffer, TextSearchService, textStructureNavigator) as ITagger<T>;
    }
    

Compilazione e test del codice

Per testare questo codice, compilare la soluzione di HighlightWordTest ed eseguirla nell'istanza sperimentale.

Per compilare e testare la soluzione di HighlightWordTest

  1. Compilare la soluzione.

  2. Quando si esegue il progetto nel debugger, una seconda istanza di Visual Studio viene creata un'istanza.

  3. Creare un file di testo e digitare un testo in cui le parole vengono ripetute, ad esempio, “hello hello hello„.

  4. Posizionare il cursore in una delle occorrenze di “hello„. ogni occorrenza dovrebbe essere evidenziata in blu.

Vedere anche

Attività

procedura dettagliata: Collegare un tipo di contenuto a un'estensione di file