procedura dettagliata: Visualizzazione dello SmartTags
Gli smart tag sono tag sul testo che si espandono per visualizzare un insieme di azioni. Ad esempio, in un progetto Visual c# o Visual Basic, una linea rossa sotto una parola quando si rinomina un identificatore come un nome di variabile. Quando si sposta il puntatore sulla sottolineatura, viene visualizzato un pulsante al puntatore. Se si fa clic sul pulsante, un'azione suggerita visualizzare, ad esempio, rinominare IsRead a IsReady. Se si fa clic sull'azione, tutti i riferimenti a IsRead nel progetto vengono rinominati IsReady.
Sebbene gli smart tag fanno parte dell'implementazione di IntelliSense nell'editor, è possibile distribuire gli smart tag dalla creazione di una sottoclasse SmartTagquindi implementare l'interfaccia di ITagger e l'interfaccia di IViewTaggerProvider .
Nota
Altri tipi di tag possono essere distribuiti in modo simile.
Di seguito viene illustrato procedura dettagliata viene illustrato come creare uno smart tag visualizzata sulla parola corrente e di due azioni suggerite: Conversione in lettere maiuscole e Conversione in minuscolo.
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 gestito Framework (MEF) di estensibilità
Per creare un progetto MEF
Creare un progetto di classificatore editor. Assegnare alla soluzione SmartTagTest.
Aprire il file source.extension.vsixmanifest nell'editor del manifesto VSIX.
Assicurarsi che la direzione di Content contenga un tipo di contenuto componente MEF e che Path è impostato su SmartTagTest.dll.
salvare e chiudere source.extension.vsixmanifest.
Aggiungere il seguente riferimento al progetto e CopyLocal impostato su false:
Microsoft.VisualStudio.Language.Intellisense
Eliminare i file di classe esistenti.
implementare un Tagger per gli smart tag
Per implementare un tagger per gli smart tag
Aggiungere il file di classe e denominarlo TestSmartTag.
Aggiungere i seguenti elementi importati:
Imports System Imports System.Collections.Generic Imports System.ComponentModel.Composition Imports System.Collections.ObjectModel Imports System.Windows.Media Imports Microsoft.VisualStudio.Language.Intellisense Imports Microsoft.VisualStudio.Text 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.Collections.ObjectModel; using System.Windows.Media; using Microsoft.VisualStudio.Language.Intellisense; using Microsoft.VisualStudio.Text; using Microsoft.VisualStudio.Text.Editor; using Microsoft.VisualStudio.Text.Operations; using Microsoft.VisualStudio.Text.Tagging; using Microsoft.VisualStudio.Utilities;
Aggiungere TestSmartTag classe denominata che eredita da SmartTag.
Friend Class TestSmartTag Inherits SmartTag
internal class TestSmartTag : SmartTag
Aggiungere un costruttore a questa classe che chiama il costruttore di base con SmartTagType di Factoid, che provocano l'interruzione di una linea blu a essere visualizzato sotto il primo carattere di una parola. (Se si utilizza Ephemeral, una riga rossa verrà visualizzato sotto dell'ultimo carattere della parola.)
Public Sub New(ByVal actionSets As ReadOnlyCollection(Of SmartTagActionSet)) MyBase.New(SmartTagType.Factoid, actionSets) End Sub
public TestSmartTag(ReadOnlyCollection<SmartTagActionSet> actionSets) : base(SmartTagType.Factoid, actionSets) { }
Aggiungere TestSmartTagger classe denominata che eredita da ITagger di tipo TestSmartTage distribuito IDisposable.
Friend Class TestSmartTagger Implements ITagger(Of TestSmartTag), IDisposable
internal class TestSmartTagger : ITagger<TestSmartTag>, IDisposable
Aggiungere i seguenti campi privati nella classe di tagger.
Private m_buffer As ITextBuffer Private m_view As ITextView Private m_provider As TestSmartTaggerProvider Private m_disposed As Boolean
private ITextBuffer m_buffer; private ITextView m_view; private TestSmartTaggerProvider m_provider; private bool m_disposed;
Aggiungere un costruttore che imposta i campi privati e sottoscritto l'evento di LayoutChanged .
Public Sub New(ByVal buffer As ITextBuffer, ByVal view As ITextView, ByVal provider As TestSmartTaggerProvider) m_buffer = buffer m_view = view m_provider = provider AddHandler m_view.LayoutChanged, AddressOf OnLayoutChanged End Sub
public TestSmartTagger(ITextBuffer buffer, ITextView view, TestSmartTaggerProvider provider) { m_buffer = buffer; m_view = view; m_provider = provider; m_view.LayoutChanged += OnLayoutChanged; }
Implement GetTags so that the tag is created for the current word. (Questo metodo chiama inoltre un metodo privato GetSmartTagActions che viene spiegato più avanti.)
Public Function GetTags(ByVal spans As NormalizedSnapshotSpanCollection) As IEnumerable(Of ITagSpan(Of TestSmartTag)) Implements ITagger(Of TestSmartTag).GetTags Dim snapshot As ITextSnapshot = m_buffer.CurrentSnapshot If snapshot.Length = 0 Then Return Nothing Exit Function End If 'set up the navigator Dim navigator As ITextStructureNavigator = m_provider.NavigatorService.GetTextStructureNavigator(m_buffer) 'set up a list to contain the tags Dim list As List(Of TagSpan(Of TestSmartTag)) list = New List(Of TagSpan(Of TestSmartTag))() For Each span In spans Dim caret As ITextCaret = m_view.Caret Dim point As SnapshotPoint If CInt(caret.Position.BufferPosition) > 0 Then point = caret.Position.BufferPosition - 1 Else Exit For End If Dim extent As TextExtent = navigator.GetExtentOfWord(point) 'don't display the tag if the extent has whitespace If extent.IsSignificant Then list.Add(New TagSpan(Of TestSmartTag)(extent.Span, New TestSmartTag(GetSmartTagActions(extent.Span)))) Else Exit For End If Next span Return list End Function
public IEnumerable<ITagSpan<TestSmartTag>> GetTags(NormalizedSnapshotSpanCollection spans) { ITextSnapshot snapshot = m_buffer.CurrentSnapshot; if (snapshot.Length == 0) yield break; //don't do anything if the buffer is empty //set up the navigator ITextStructureNavigator navigator = m_provider.NavigatorService.GetTextStructureNavigator(m_buffer); foreach (var span in spans) { ITextCaret caret = m_view.Caret; SnapshotPoint point; if (caret.Position.BufferPosition > 0) point = caret.Position.BufferPosition - 1; else yield break; TextExtent extent = navigator.GetExtentOfWord(point); //don't display the tag if the extent has whitespace if (extent.IsSignificant) yield return new TagSpan<TestSmartTag>(extent.Span, new TestSmartTag(GetSmartTagActions(extent.Span))); else yield break; } }
Aggiungere un metodo di GetSmartTagActions per impostare le azioni smart tag. Le azioni sono implementate nei passaggi successivi.
Private Function GetSmartTagActions(ByVal span As SnapshotSpan) As ReadOnlyCollection(Of SmartTagActionSet) Dim actionSetList As New List(Of SmartTagActionSet)() Dim actionList As New List(Of ISmartTagAction)() Dim trackingSpan As ITrackingSpan = span.Snapshot.CreateTrackingSpan(span, SpanTrackingMode.EdgeInclusive) actionList.Add(New UpperCaseSmartTagAction(trackingSpan)) actionList.Add(New LowerCaseSmartTagAction(trackingSpan)) Dim actionSet As New SmartTagActionSet(actionList.AsReadOnly()) actionSetList.Add(actionSet) Return actionSetList.AsReadOnly() End Function
private ReadOnlyCollection<SmartTagActionSet> GetSmartTagActions(SnapshotSpan span) { List<SmartTagActionSet> actionSetList = new List<SmartTagActionSet>(); List<ISmartTagAction> actionList = new List<ISmartTagAction>(); ITrackingSpan trackingSpan = span.Snapshot.CreateTrackingSpan(span, SpanTrackingMode.EdgeInclusive); actionList.Add(new UpperCaseSmartTagAction(trackingSpan)); actionList.Add(new LowerCaseSmartTagAction(trackingSpan)); SmartTagActionSet actionSet = new SmartTagActionSet(actionList.AsReadOnly()); actionSetList.Add(actionSet); return actionSetList.AsReadOnly(); }
dichiarare l'evento di SmartTagsChanged .
Public Event TagsChanged As EventHandler(Of SnapshotSpanEventArgs) Implements ITagger(Of TestSmartTag).TagsChanged
public event EventHandler<SnapshotSpanEventArgs> TagsChanged;
Implementare il gestore eventi di OnLayoutChanged per generare l'evento di TagsChanged , che comporta l'entity_M:Microsoft.VisualStudio.Text.Tagging.ITagger`1.GetTags(Microsoft.VisualStudio.Text.NormalizedSnapshotSpanCollection) a essere chiamato.
Private Sub OnLayoutChanged(ByVal sender As Object, ByVal e As TextViewLayoutChangedEventArgs) Dim snapshot As ITextSnapshot = e.NewSnapshot 'don't do anything if this is just a change in case If Not snapshot.GetText().ToLower().Equals(e.OldSnapshot.GetText().ToLower()) Then Dim span As New SnapshotSpan(snapshot, New Span(0, snapshot.Length)) Dim handler As EventHandler(Of SnapshotSpanEventArgs) = Me.TagsChangedEvent If handler IsNot Nothing Then handler(Me, New SnapshotSpanEventArgs(span)) End If End If End Sub
private void OnLayoutChanged(object sender, TextViewLayoutChangedEventArgs e) { ITextSnapshot snapshot = e.NewSnapshot; //don't do anything if this is just a change in case if (!snapshot.GetText().ToLower().Equals(e.OldSnapshot.GetText().ToLower())) { SnapshotSpan span = new SnapshotSpan(snapshot, new Span(0, snapshot.Length)); EventHandler<SnapshotSpanEventArgs> handler = this.TagsChanged; if (handler != null) { handler(this, new SnapshotSpanEventArgs(span)); } } }
Implementare il metodo di Dispose in modo che disdica dall'evento di LayoutChanged .
Public Sub Dispose() Implements IDisposable.Dispose Dispose(True) GC.SuppressFinalize(Me) End Sub Private Sub Dispose(ByVal disposing As Boolean) If disposing Then RemoveHandler m_view.LayoutChanged, AddressOf OnLayoutChanged m_view = Nothing End If m_disposed = True End Sub
public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } private void Dispose(bool disposing) { if (!this.m_disposed) { if (disposing) { m_view.LayoutChanged -= OnLayoutChanged; m_view = null; } m_disposed = true; } }
Implementare il provider di Tagger smart tag
Per implementare il provider di tagger smart tag
Aggiungere TestSmartTagTaggerProvider classe denominata che eredita da IViewTaggerProvider. Esportarlo con ContentTypeAttribute di “testo„, OrderAttribute di Before= " default„ e TagTypeAttribute di SmartTag.
<Export(GetType(IViewTaggerProvider))> <ContentType("text")> <Order(Before:="default")> <TagType(GetType(SmartTag))> Friend Class TestSmartTaggerProvider Implements IViewTaggerProvider
[Export(typeof(IViewTaggerProvider))] [ContentType("text")] [Order(Before = "default")] [TagType(typeof(SmartTag))] internal class TestSmartTaggerProvider : IViewTaggerProvider
Importare ITextStructureNavigatorSelectorService come proprietà.
<Import(GetType(ITextStructureNavigatorSelectorService))> Friend Property NavigatorService() As ITextStructureNavigatorSelectorService
[Import(typeof(ITextStructureNavigatorSelectorService))] internal ITextStructureNavigatorSelectorService NavigatorService { get; set; }
Implementare il metodo CreateTagger``1.
Public Function CreateTagger(Of T As ITag)(ByVal textView As ITextView, ByVal buffer As ITextBuffer) As ITagger(Of T) Implements IViewTaggerProvider.CreateTagger If buffer Is Nothing OrElse textView Is Nothing Then Return Nothing End If 'make sure we are tagging only the top buffer If buffer Is textView.TextBuffer Then Return New TestSmartTagger(buffer, textView, Me) Else Return Nothing End If End Function
public ITagger<T> CreateTagger<T>(ITextView textView, ITextBuffer buffer) where T : ITag { if (buffer == null || textView == null) { return null; } //make sure we are tagging only the top buffer if (buffer == textView.TextBuffer) { return new TestSmartTagger(buffer, textView, this) as ITagger<T>; } else return null; }
Implementare le azioni smart tag
Per implementare le azioni smart tag
Creare due classi, primo UpperCaseSmartTagAction denominato e come LowerCaseSmartTagActiondenominato. entrambe le classi implementano ISmartTagAction.
Friend Class UpperCaseSmartTagAction Implements ISmartTagAction
internal class UpperCaseSmartTagAction : ISmartTagAction
Friend Class LowerCaseSmartTagAction Implements ISmartTagAction
internal class LowerCaseSmartTagAction : ISmartTagAction
Entrambe le classi sono simili ma si chiama ToUpper e l'altro chiama ToLower. Nell'analizzare i passaggi solo la classe maiuscola di azione, ma è necessario implementare entrambe le classi. Utilizzare i passaggi per la distribuzione l'azione maiuscola come modello per implementare l'azione minuscole.
dichiarare un set di campi privati.
Private m_span As ITrackingSpan Private m_upper As String Private m_display As String Private m_snapshot As ITextSnapshot
private ITrackingSpan m_span; private string m_upper; private string m_display; private ITextSnapshot m_snapshot;
aggiungere un costruttore che imposta i campi.
Public Sub New(ByVal span As ITrackingSpan) m_span = span m_snapshot = span.TextBuffer.CurrentSnapshot m_upper = span.GetText(m_snapshot).ToUpper() m_display = "Convert to upper case" End Sub
public UpperCaseSmartTagAction(ITrackingSpan span) { m_span = span; m_snapshot = span.TextBuffer.CurrentSnapshot; m_upper = span.GetText(m_snapshot).ToUpper(); m_display = "Convert to upper case"; }
Implementare le proprietà seguenti.
Public ReadOnly Property DisplayText() As String Implements ISmartTagAction.DisplayText Get Return m_display End Get End Property Public ReadOnly Property Icon() As ImageSource Implements ISmartTagAction.Icon Get Return Nothing End Get End Property Public ReadOnly Property IsEnabled() As Boolean Implements ISmartTagAction.IsEnabled Get Return True End Get End Property Private privateSource As ISmartTagSource Public Property Source() As ISmartTagSource Get Return privateSource End Get Private Set(ByVal value As ISmartTagSource) privateSource = value End Set End Property Public ReadOnly Property ActionSets() As ReadOnlyCollection(Of SmartTagActionSet) Implements ISmartTagAction.ActionSets Get Return Nothing End Get End Property
public string DisplayText { get { return m_display; } } public ImageSource Icon { get { return null; } } public bool IsEnabled { get { return true; } } public ISmartTagSource Source { get; private set; } public ReadOnlyCollection<SmartTagActionSet> ActionSets { get { return null; } }
Implementare il metodo di Invoke sostituendo il testo nell'ampiezza con il relativo equivalente maiuscolo.
Public Sub Invoke() Implements ISmartTagAction.Invoke m_span.TextBuffer.Replace(m_span.GetSpan(m_snapshot), m_upper) End Sub
public void Invoke() { m_span.TextBuffer.Replace(m_span.GetSpan(m_snapshot), m_upper); }
Compilazione e test del codice
Per testare questo codice, compilare la soluzione di SmartTagTest ed eseguirla nell'istanza sperimentale.
Per compilare e testare la soluzione di SmartTagTest
Compilare la soluzione.
Quando si esegue il progetto nel debugger, una seconda istanza di Visual Studio viene creata un'istanza.
Creare un file di testo e digitare un testo.
Una linea blu deve essere visualizzati sotto la prima lettera della prima parola di testo.
Spostare il puntatore sulla linea blu.
Un pulsante dovrebbe essere visualizzata accanto al puntatore.
Quando si fa clic sul pulsante, due hanno suggerito che le azioni devono essere visualizzati: Conversione in lettere maiuscole e Conversione in minuscolo. Se si fa clic sulla prima azione, tutto il testo della parola corrente deve essere convertito in maiuscolo. Se si fa clic sulla seconda azione, tutto il testo deve essere convertito in minuscolo.
Vedere anche
Attività
procedura dettagliata: Collegare un tipo di contenuto a un'estensione di file