다음을 통해 공유


연습: 스마트 태그 표시

스마트 태그 작업 집합을 표시 하는 확장 태그 텍스트입니다. 예를 들어, 변수 이름이 같은 식별자의 이름을 바꿀 때 단어에서 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 추가 합니다.

    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 it에서 등록을 취소 하도록 메서드를 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 의 전 "기본" = a 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. 이 단추를 클릭 하면 두 작업 표시 제안: 를 대문자로 변환소문자로 변환. 첫 번째 작업을 클릭 하면 현재 단어의 모든 텍스트를 대문자로 변환 합니다. 두 번째 작업을 클릭 하면 텍스트를 모두 소문자로 변환 합니다.

참고 항목

작업

연습: 콘텐츠 형식의 파일 이름 확장명에 연결