共用方式為


逐步解說: 顯示智慧標籤

智慧標籤會展開以顯示一組巨集的標籤文字。 比方說,在 Visual Basic 或視覺化 C# 的專案中,一條紅線出現在 [文字] 下重新命名的識別項,例如變數名稱時。 當您將指標移底線時,按鈕會顯示指標附近。 如果您按一下按鈕時,建議的動作會顯示,比方說, 重新命名為 IsReady 的 IsRead。 如果按一下 [動作],會重新命名專案中的所有參考到 IsRead IsReady。

雖然智慧標籤是在編輯器中的 IntelliSense 實作的一部分,您可以由子類別化,實作智慧標籤SmartTag,然後再實作ITagger介面和IViewTaggerProvider介面。

注意事項注意事項

以類似的方式,可以實作其他種類的標籤。

下列逐步解說會示範如何建立智慧標籤,就會出現在目前的文字,並有兩個建議的動作: 轉換成大寫轉換成小寫字母

必要條件

若要完成這個逐步解說中,您必須安裝Visual Studio 2010 SDK。

注意事項注意事項

如需有關 Visual Studio 的 SDK 的詳細資訊,請參閱擴充 Visual Studio 的概觀。若要了解如何下載 Visual Studio 的 SDK,請參閱Visual Studio 擴充性開發人員中心 MSDN 網站上。

建立受管理的擴充性架構 (MEF) 專案

若要建立 MEF 專案

  1. 建立編輯器類別器的專案。 為方案命名 SmartTagTest。

  2. VSIX 資訊清單編輯器中開啟 source.extension.vsixmanifest 檔案。

  3. 請確定Content名包含 MEF 元件的內容類型,並Path設定為 SmartTagTest.dll。

  4. 儲存並關閉 source.extension.vsixmanifest。

  5. 將下列參考加入至專案,並設定 CopyLocal 到false:

    Microsoft.VisualStudio.Language.Intellisense

  6. 刪除現有的類別檔案。

智慧標籤實作的 Tagger

若要實作智慧標籤的 tagger

  1. 將類別檔案,並命名為 TestSmartTag。

  2. 加入下列匯入:

    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;
    
  3. 新增類別,名為TestSmartTag繼承自SmartTag

    Friend Class TestSmartTag
        Inherits SmartTag
    
    internal class TestSmartTag : SmartTag
    
  4. 加入具有基底建構函式會呼叫這個類別的建構函式SmartTagTypeFactoid,這樣將會造成在下一個字的第一個字元出現在藍色線條。 (如果您使用Ephemeral,一條紅線會出現這個字的最後一個字元下。)

    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) { }
    
  5. 新增類別,名為TestSmartTagger繼承自ITagger型別的TestSmartTag,並實作IDisposable

    Friend Class TestSmartTagger
        Implements ITagger(Of TestSmartTag), IDisposable
    
    internal class TestSmartTagger : ITagger<TestSmartTag>, IDisposable
    
  6. 將下列私用欄位加入 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;
    
  7. 新增的建構函式將私用欄位中,然後訂閱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;
    }
    
  8. 實作GetTags ,以便為目前的文字建立標籤。 (此方法也會呼叫私用方法GetSmartTagActions ,稍後會加以說明。)

    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;
        }
    }
    
  9. 新增GetSmartTagActions方法,以設定 [智慧標籤動作。 在後面幾個步驟中實作本身的動作。

    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();
    }
    
  10. 宣告SmartTagsChanged事件。

    Public Event TagsChanged As EventHandler(Of SnapshotSpanEventArgs) Implements ITagger(Of TestSmartTag).TagsChanged
    
    public event EventHandler<SnapshotSpanEventArgs> TagsChanged;
    
  11. 實作OnLayoutChanged要引發的事件處理常式TagsChanged事件,這可以讓GetTags呼叫。

    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));
            }
        }
    }
    
  12. 實作Dispose方法,讓它取消訂閱從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;
        }
    }
    

實作智慧標籤 Tagger 提供者

若要實作智慧標籤 tagger 提供者

  1. 新增類別,名為TestSmartTagTaggerProvider繼承自IViewTaggerProvider。 匯出與ContentTypeAttribute的 「 文字 」, OrderAttribute的早於 ="default",和TagTypeAttributeSmartTag

    <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
    
  2. 匯入ITextStructureNavigatorSelectorService做為屬性。

    <Import(GetType(ITextStructureNavigatorSelectorService))>
    Friend Property NavigatorService() As ITextStructureNavigatorSelectorService
    
    [Import(typeof(ITextStructureNavigatorSelectorService))]
    internal ITextStructureNavigatorSelectorService NavigatorService { get; set; }
    
  3. 實作 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;
    }
    

實作智慧標籤動作

若要實作智慧標籤動作

  • 建立兩個類別,第一個名為 UpperCaseSmartTagAction ,而第二個名為 LowerCaseSmartTagAction。 這兩個類別會實作ISmartTagAction

    Friend Class UpperCaseSmartTagAction
        Implements ISmartTagAction
    
    internal class UpperCaseSmartTagAction : ISmartTagAction
    
    Friend Class LowerCaseSmartTagAction
        Implements ISmartTagAction
    
    internal class LowerCaseSmartTagAction : ISmartTagAction
    

這兩個類別是相同的不同之處在於其中一個會呼叫ToUpper及其他呼叫ToLower。 下列步驟涵蓋只有大寫動作類別,但您必須實作這兩個類別。 請使用步驟的實作模式實作的大小寫的動作為大寫的動作。

  1. 宣告一組的私用欄位。

    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;
    
  2. 加入建構函式所設定的欄位。

    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";
    }
    
  3. 以下列方式實作的屬性。

    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; }
    }
    
  4. 實作Invoke以同等項目取代的文字範圍中的方法。

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

建置和測試程式碼

若要測試這段程式碼,建置 SmartTagTest 方案並執行它實驗性的執行個體中。

若要建置和測試 SmartTagTest 的解決方案

  1. 建置方案。

  2. 當您執行此專案在偵錯工具時,會執行個體化 Visual Studio 的第二個執行個體。

  3. 建立一個文字檔,並輸入一些文字。

    在 [文字的第一個單字的第一個字母] 下,應該會顯示藍線。

  4. 指標移動過藍線。

    指標附近,應該會顯示一個按鈕。

  5. 當您按一下按鈕時,兩個建議的動作應該會顯示: 轉換成大寫轉換成小寫字母。 如果您按一下第一個動作時,就應該在目前的 word 中的所有文字都轉換成大寫。 如果您按一下第二個動作時,所有的文字應轉換成小寫字母。

請參閱

工作

逐步解說: 連結至檔案的副檔名的內容類型