共用方式為


逐步解說: 顯示陳述式完成

您可以定義您要提供完成的功能,識別的項,並接著觸發完成的工作階段,以實作語言為基礎的功能,例如陳述式完成。 您可以定義陳述式完成語言服務層,或您可以定義自己的檔案名稱副檔名和內容類型,並顯示的只是該型別,完成或現有的內容類型 (例如 「 純文字 」) 的完成觸發程序。 這個逐步解說會示範如何以觸發 「 純文字 」 的內容類型,也就是文字檔的內容類型的陳述式完成。 「 文字 」 內容類型是所有其他內容類型,包括程式碼和 XML 檔案的上階。

鍵入如 「 使用 」 的識別項開頭輸入特定字元,例如,通常觸發陳述式完成。 它通常是藉由按下空格鍵、 TAB 或 ENTER 認可的選取項目關閉。 可以使用按鍵輸入的命令處理常式實作 IntelliSense 所觸發的輸入字元之外的功能 ( IOleCommandTarget介面) 和處理常式提供者實作IVsTextViewCreationListener介面。 若要建立完成來源,也就是完成所參與的識別項的清單,實作ICompletionSource介面,並完成原始檔提供者 ( ICompletionSourceProvider介面)。 提供者管理擴充性架構 (MEF) 元件組件,而負責匯出的來源和控制器類別和匯入的服務和經紀人,比方說, ITextStructureNavigatorSelectorService,可讓您瀏覽文字緩衝區中,以及ICompletionBroker,而觸發程序完成的工作階段。

這個逐步解說會示範如何實作硬式編碼的組的識別項的陳述式完成。 在完整的實作中,語言服務和語言文件都是負責提供該內容。

必要條件

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

注意事項注意事項

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

建立 MEF 專案

若要建立 MEF 專案

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

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

  3. 請確定內容 名包含 MEF 元件 內容,如果其中 路徑 設定為 [ CompletionTest.dll

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

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

    Microsoft.VisualStudio.Editor

    Microsoft.VisualStudio.Language.Intellisense

    Microsoft.VisualStudio.OLE.Interop

    Microsoft.VisualStudio.Shell.10.0

    Microsoft.VisualStudio.Shell.Immutable.10.0

    Microsoft.VisualStudio.TextManager.Interop

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

實作完成來源

完成來源是負責收集組的識別項和使用者輸入的完成觸發程序,例如識別項的第一個字母時,將內容加入至 [完成] 視窗。 在這個範例中,識別項和其描述會硬式編碼在AugmentCompletionSession方法。 在大多數實際用途,您會使用您的語言剖析器取得語彙基元,以填入完成清單。

若要實作完成來源

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

  2. 加入下列匯入。

    Imports System
    Imports System.Collections.Generic
    Imports System.Linq
    Imports System.Text
    Imports System.ComponentModel.Composition
    Imports Microsoft.VisualStudio.Language.Intellisense
    Imports Microsoft.VisualStudio.Text
    Imports Microsoft.VisualStudio.Text.Operations
    Imports Microsoft.VisualStudio.Utilities
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ComponentModel.Composition;
    using Microsoft.VisualStudio.Language.Intellisense;
    using Microsoft.VisualStudio.Text;
    using Microsoft.VisualStudio.Text.Operations;
    using Microsoft.VisualStudio.Utilities;
    
  3. 修改類別宣告,如TestCompletionSource ,這樣它會實作ICompletionSource

    Friend Class TestCompletionSource
        Implements ICompletionSource
    
    internal class TestCompletionSource : ICompletionSource
    
  4. 加入私用欄位的原始檔提供者、 文字緩衝區,以及一份Completion (這會對應到要參與完成的工作階段識別項) 的物件。

    Private m_sourceProvider As TestCompletionSourceProvider
    Private m_textBuffer As ITextBuffer
    Private m_compList As List(Of Completion)
    
    private TestCompletionSourceProvider m_sourceProvider;
    private ITextBuffer m_textBuffer;
    private List<Completion> m_compList;
    
  5. 加入建構函式會設定來源提供者和緩衝區。 TestCompletionSourceProvider 類別被定義在後面幾個步驟。

    Public Sub New(ByVal sourceProvider As TestCompletionSourceProvider, ByVal textBuffer As ITextBuffer)
        m_sourceProvider = sourceProvider
        m_textBuffer = textBuffer
    End Sub
    
    public TestCompletionSource(TestCompletionSourceProvider sourceProvider, ITextBuffer textBuffer)
    {
        m_sourceProvider = sourceProvider;
        m_textBuffer = textBuffer;
    }
    
  6. 實作AugmentCompletionSession您想要在內容中所提供的方法,藉由加入完成集,其中包含完整的指令。 每個完成集包含一群Completion完整的指令,而對應的索引標籤的 [完成] 視窗。 (在 Visual Basic 專案中,完成視窗索引標籤名為一般所有。) FindTokenSpanAtPosition 方法定義於下一個步驟。

    Private Sub AugmentCompletionSession(ByVal session As ICompletionSession, ByVal completionSets As IList(Of CompletionSet)) Implements ICompletionSource.AugmentCompletionSession
        Dim strList As New List(Of String)()
        strList.Add("addition")
        strList.Add("adaptation")
        strList.Add("subtraction")
        strList.Add("summation")
    
        m_compList = New List(Of Completion)()
        For Each str As String In strList
            m_compList.Add(New Completion(str, str, str, Nothing, Nothing))
        Next str
    
        completionSets.Add(New CompletionSet(
            "Tokens",
            "Tokens",
            FindTokenSpanAtPosition(session.GetTriggerPoint(m_textBuffer),
                session),
            m_compList,
            Nothing))
    End Sub
    
    void ICompletionSource.AugmentCompletionSession(ICompletionSession session, IList<CompletionSet> completionSets)
    {
        List<string> strList = new List<string>();
        strList.Add("addition");
        strList.Add("adaptation");
        strList.Add("subtraction");
        strList.Add("summation");
        m_compList = new List<Completion>();
        foreach (string str in strList)
            m_compList.Add(new Completion(str, str, str, null, null));
    
        completionSets.Add(new CompletionSet(
            "Tokens",    //the non-localized title of the tab 
            "Tokens",    //the display title of the tab
            FindTokenSpanAtPosition(session.GetTriggerPoint(m_textBuffer),
                session),
            m_compList,
            null));
    }
    
  7. 下列的方法用來尋找目前的文字從插入號位置。

    Private Function FindTokenSpanAtPosition(ByVal point As ITrackingPoint, ByVal session As ICompletionSession) As ITrackingSpan
        Dim currentPoint As SnapshotPoint = (session.TextView.Caret.Position.BufferPosition) - 1
        Dim navigator As ITextStructureNavigator = m_sourceProvider.NavigatorService.GetTextStructureNavigator(m_textBuffer)
        Dim extent As TextExtent = navigator.GetExtentOfWord(currentPoint)
        Return currentPoint.Snapshot.CreateTrackingSpan(extent.Span, SpanTrackingMode.EdgeInclusive)
    End Function
    
    private ITrackingSpan FindTokenSpanAtPosition(ITrackingPoint point, ICompletionSession session)
    {
        SnapshotPoint currentPoint = (session.TextView.Caret.Position.BufferPosition) - 1;
        ITextStructureNavigator navigator = m_sourceProvider.NavigatorService.GetTextStructureNavigator(m_textBuffer);
        TextExtent extent = navigator.GetExtentOfWord(currentPoint);
        return currentPoint.Snapshot.CreateTrackingSpan(extent.Span, SpanTrackingMode.EdgeInclusive);
    }
    
  8. 實作 dispose () 方法:

    Private m_isDisposed As Boolean 
    Public Sub Dispose() Implements IDisposable.Dispose
        If Not m_isDisposed Then
            GC.SuppressFinalize(Me)
            m_isDisposed = True 
        End If 
    End Sub
    
    private bool m_isDisposed;
    public void Dispose()
    {
        if (!m_isDisposed)
        {
            GC.SuppressFinalize(this);
            m_isDisposed = true;
        }
    }
    

實作完成來源提供者

完成原始檔提供者會具現化完成來源 MEF 元件組件。

若要實作完成原始檔提供者

  1. 新增類別,名為TestCompletionSourceProvider實作ICompletionSourceProvider。 匯出類別與ContentTypeAttribute 「 純文字 」,並NameAttribute的 「 測試完成 」。

    <Export(GetType(ICompletionSourceProvider)), ContentType("plaintext"), Name("token completion")>
    Friend Class TestCompletionSourceProvider
        Implements ICompletionSourceProvider
    
    [Export(typeof(ICompletionSourceProvider))]
    [ContentType("plaintext")]
    [Name("token completion")]
    internal class TestCompletionSourceProvider : ICompletionSourceProvider
    
  2. 匯入ITextStructureNavigatorSelectorService,這是用來完成來源中尋找目前的文字。

    <Import()>
    Friend Property NavigatorService() As ITextStructureNavigatorSelectorService
    
    [Import]
    internal ITextStructureNavigatorSelectorService NavigatorService { get; set; }
    
  3. 實作TryCreateCompletionSource方法來具現化完成來源。

    Public Function TryCreateCompletionSource(ByVal textBuffer As ITextBuffer) As ICompletionSource Implements ICompletionSourceProvider.TryCreateCompletionSource
        Return New TestCompletionSource(Me, textBuffer)
    End Function
    
    public ICompletionSource TryCreateCompletionSource(ITextBuffer textBuffer)
    {
        return new TestCompletionSource(this, textBuffer);
    }
    

實作完成命令處理常式提供者

完成命令處理常式提供者衍生自IVsTextViewCreationListener,它會接聽的文字檢視建立事件,並將轉換從檢視IVsTextView (這可讓命令加入至 Visual Studio 的殼層命令鏈結) 至ITextView。 由於這個類別是 MEF 匯出,您也可以使用它來匯入命令處理常式本身所需的服務。

若要實作完成命令處理常式提供者

  1. 新增名為 TestCompletionCommandHandler 的檔案。

  2. 將下列 using 陳述式。

    Imports System
    Imports System.Collections.Generic
    Imports System.Linq
    Imports System.Text
    Imports System.ComponentModel.Composition
    Imports System.Runtime.InteropServices
    Imports Microsoft.VisualStudio
    Imports Microsoft.VisualStudio.Editor
    Imports Microsoft.VisualStudio.Language.Intellisense
    Imports Microsoft.VisualStudio.OLE.Interop
    Imports Microsoft.VisualStudio.Shell
    Imports Microsoft.VisualStudio.Text
    Imports Microsoft.VisualStudio.Text.Editor
    Imports Microsoft.VisualStudio.TextManager.Interop
    Imports Microsoft.VisualStudio.Utilities
    
    using System;
    using System.ComponentModel.Composition;
    using System.Runtime.InteropServices;
    using Microsoft.VisualStudio;
    using Microsoft.VisualStudio.Editor;
    using Microsoft.VisualStudio.Language.Intellisense;
    using Microsoft.VisualStudio.OLE.Interop;
    using Microsoft.VisualStudio.Shell;
    using Microsoft.VisualStudio.Text;
    using Microsoft.VisualStudio.Text.Editor;
    using Microsoft.VisualStudio.TextManager.Interop;
    using Microsoft.VisualStudio.Utilities;
    
  3. 新增類別,名為TestCompletionHandlerProvider實作IVsTextViewCreationListener。 匯出類別與NameAttribute "語彙基元完成處理程式 」, ContentTypeAttribute 「 純文字 」,以及TextViewRoleAttributeEditable

    <Export(GetType(IVsTextViewCreationListener))>
    <Name("token completion handler")>
    <ContentType("plaintext")> <TextViewRole(PredefinedTextViewRoles.Editable)>
    Friend Class TestCompletionHandlerProvider
        Implements IVsTextViewCreationListener
    
    [Export(typeof(IVsTextViewCreationListener))]
    [Name("token completion handler")]
    [ContentType("plaintext")]
    [TextViewRole(PredefinedTextViewRoles.Editable)]
    internal class TestCompletionHandlerProvider : IVsTextViewCreationListener
    
  4. 匯入IVsEditorAdaptersFactoryService,可讓您將IVsTextViewITextViewICompletionBroker,以及SVsServiceProvider,它可讓您存取標準的 Visual Studio 服務。.

    <Import()>
    Friend AdapterService As IVsEditorAdaptersFactoryService = Nothing
    <Import()>
    Friend Property CompletionBroker() As ICompletionBroker
    <Import()>
    Friend Property ServiceProvider() As SVsServiceProvider
    
    [Import]
    internal IVsEditorAdaptersFactoryService AdapterService = null;
    [Import]
    internal ICompletionBroker CompletionBroker { get; set; }
    [Import]
    internal SVsServiceProvider ServiceProvider { get; set; }
    
  5. 實作VsTextViewCreated來具現化命令處理常式的方法。

    Public Sub VsTextViewCreated(ByVal textViewAdapter As IVsTextView) Implements IVsTextViewCreationListener.VsTextViewCreated
        Dim textView As ITextView = AdapterService.GetWpfTextView(textViewAdapter)
        If textView Is Nothing Then 
            Return 
        End If 
    
        Dim createCommandHandler As Func(Of TestCompletionCommandHandler) = Function() New TestCompletionCommandHandler(textViewAdapter, textView, Me)
        textView.Properties.GetOrCreateSingletonProperty(createCommandHandler)
    End Sub
    
    public void VsTextViewCreated(IVsTextView textViewAdapter)
    {
        ITextView textView = AdapterService.GetWpfTextView(textViewAdapter);
        if (textView == null)
            return;
    
        Func<TestCompletionCommandHandler> createCommandHandler = delegate() { return new TestCompletionCommandHandler(textViewAdapter, textView, this); };
        textView.Properties.GetOrCreateSingletonProperty(createCommandHandler);
    }
    

實作完成命令處理常式

您必須實作的陳述式完成時,觸發的按鍵動作,因為IOleCommandTarget介面來接收和處理的觸發程序、 認可和關閉完成的工作階段的按鍵動作。

若要實作完成命令處理常式

  1. 新增類別,名為TestCompletionCommandHandler實作IOleCommandTarget

    Friend Class TestCompletionCommandHandler
        Implements IOleCommandTarget
    
    internal class TestCompletionCommandHandler : IOleCommandTarget
    
  2. 加入私用欄位下, 一個命令處理常式 (要傳遞的命令)、 [文字] 檢視、 命令處理常式提供者 (這可讓您存取各項服務的資訊),而將完成的工作階段。

    Private m_nextCommandHandler As IOleCommandTarget
    Private m_textView As ITextView
    Private m_provider As TestCompletionHandlerProvider
    Private m_session As ICompletionSession
    
    private IOleCommandTarget m_nextCommandHandler;
    private ITextView m_textView;
    private TestCompletionHandlerProvider m_provider;
    private ICompletionSession m_session;
    
  3. 加入建構函式,設定 [文字] 檢視和 [提供者] 欄位中,並將命令加入至命令鏈結。

    Friend Sub New(ByVal textViewAdapter As IVsTextView, ByVal textView As ITextView, ByVal provider As TestCompletionHandlerProvider)
        Me.m_textView = textView
        Me.m_provider = provider
    
        'add the command to the command chain
        textViewAdapter.AddCommandFilter(Me, m_nextCommandHandler)
    End Sub
    
    internal TestCompletionCommandHandler(IVsTextView textViewAdapter, ITextView textView, TestCompletionHandlerProvider provider)
    {
        this.m_textView = textView;
        this.m_provider = provider;
    
        //add the command to the command chain
        textViewAdapter.AddCommandFilter(this, out m_nextCommandHandler);
    }
    
  4. 實作QueryStatus方法,藉由傳遞以及命令。

    Public Function QueryStatus(ByRef pguidCmdGroup As Guid, ByVal cCmds As UInteger, ByVal prgCmds() As OLECMD, ByVal pCmdText As IntPtr) As Integer Implements IOleCommandTarget.QueryStatus
        Return m_nextCommandHandler.QueryStatus(pguidCmdGroup, cCmds, prgCmds, pCmdText)
    End Function
    
    public int QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText)
    {
        return m_nextCommandHandler.QueryStatus(ref pguidCmdGroup, cCmds, prgCmds, pCmdText);
    }
    
  5. 實作 Exec 方法。 當這個方法會接收按鍵動作時,則必須執行下列這些步驟:

    • 允許的字元寫入緩衝區,並接著觸發程序,或篩選的完成 (列印的字元執行)。

    • 認可完成,但不是允許的字元寫入至緩衝區 (空白、 索引標籤上,與顯示完成的工作階段時,執行這項操作的 ENTER)。

    • 允許命令傳遞至下一個處理常式 (所有其他指令)。

    因為這個方法可能會顯示 UI,您應該確定它不呼叫內容中的自動化物件藉由呼叫IsInAutomationFunction

    Public Function Exec(ByRef pguidCmdGroup As Guid, ByVal nCmdID As UInteger, ByVal nCmdexecopt As UInteger, ByVal pvaIn As IntPtr, ByVal pvaOut As IntPtr) As Integer Implements IOleCommandTarget.Exec
        If VsShellUtilities.IsInAutomationFunction(m_provider.ServiceProvider) Then 
            Return m_nextCommandHandler.Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut)
        End If 
        'make a copy of this so we can look at it after forwarding some commands 
        Dim commandID As UInteger = nCmdID
        Dim typedChar As Char = Char.MinValue
        'make sure the input is a char before getting it 
        If pguidCmdGroup = VSConstants.VSStd2K AndAlso nCmdID = CUInt(VSConstants.VSStd2KCmdID.TYPECHAR) Then
            typedChar = CChar(ChrW(CUShort(Marshal.GetObjectForNativeVariant(pvaIn))))
        End If 
    
        'check for a commit character 
        If nCmdID = CUInt(VSConstants.VSStd2KCmdID.RETURN) OrElse nCmdID = CUInt(VSConstants.VSStd2KCmdID.TAB) OrElse (Char.IsWhiteSpace(typedChar) OrElse Char.IsPunctuation(typedChar)) Then 
            'check for a a selection 
            If m_session IsNot Nothing AndAlso (Not m_session.IsDismissed) Then 
                'if the selection is fully selected, commit the current session 
                If m_session.SelectedCompletionSet.SelectionStatus.IsSelected Then
                    m_session.Commit()
                    'also, don't add the character to the buffer 
                    Return VSConstants.S_OK
                Else 
                    'if there is no selection, dismiss the session
                    m_session.Dismiss()
                End If 
            End If 
        End If 
    
        'pass along the command so the char is added to the buffer 
        Dim retVal As Integer = m_nextCommandHandler.Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut)
        Dim handled As Boolean = False 
        If (Not typedChar.Equals(Char.MinValue)) AndAlso Char.IsLetterOrDigit(typedChar) Then 
            If m_session Is Nothing OrElse m_session.IsDismissed Then ' If there is no active session, bring up completion
                Me.TriggerCompletion()
                m_session.Filter()
            Else 'the completion session is already active, so just filter
                m_session.Filter()
            End If
            handled = True 
        ElseIf commandID = CUInt(VSConstants.VSStd2KCmdID.BACKSPACE) OrElse commandID = CUInt(VSConstants.VSStd2KCmdID.DELETE) Then 'redo the filter if there is a deletion
            If m_session IsNot Nothing AndAlso (Not m_session.IsDismissed) Then
                m_session.Filter()
            End If
            handled = True 
        End If 
        If handled Then 
            Return VSConstants.S_OK
        End If 
        Return retVal
    End Function
    
    public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
    {
        if (VsShellUtilities.IsInAutomationFunction(m_provider.ServiceProvider))
        {
            return m_nextCommandHandler.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
        }
        //make a copy of this so we can look at it after forwarding some commands 
        uint commandID = nCmdID;
        char typedChar = char.MinValue;
        //make sure the input is a char before getting it 
        if (pguidCmdGroup == VSConstants.VSStd2K && nCmdID == (uint)VSConstants.VSStd2KCmdID.TYPECHAR)
        {
            typedChar = (char)(ushort)Marshal.GetObjectForNativeVariant(pvaIn);
        }
    
        //check for a commit character 
        if (nCmdID == (uint)VSConstants.VSStd2KCmdID.RETURN
            || nCmdID == (uint)VSConstants.VSStd2KCmdID.TAB
            || (char.IsWhiteSpace(typedChar) || char.IsPunctuation(typedChar)))
        {
            //check for a a selection 
            if (m_session != null && !m_session.IsDismissed)
            {
                //if the selection is fully selected, commit the current session 
                if (m_session.SelectedCompletionSet.SelectionStatus.IsSelected)
                {
                    m_session.Commit();
                    //also, don't add the character to the buffer 
                    return VSConstants.S_OK;
                }
                else
                {
                    //if there is no selection, dismiss the session
                    m_session.Dismiss();
                }
            }
        }
    
        //pass along the command so the char is added to the buffer 
        int retVal = m_nextCommandHandler.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
        bool handled = false;
        if (!typedChar.Equals(char.MinValue) && char.IsLetterOrDigit(typedChar))
        {
            if (m_session == null || m_session.IsDismissed) // If there is no active session, bring up completion
            {
                this.TriggerCompletion();
                m_session.Filter();
            }
            else     //the completion session is already active, so just filter
            {
                m_session.Filter();
            }
            handled = true;
        }
        else if (commandID == (uint)VSConstants.VSStd2KCmdID.BACKSPACE   //redo the filter if there is a deletion
            || commandID == (uint)VSConstants.VSStd2KCmdID.DELETE)
        {
            if (m_session != null && !m_session.IsDismissed)
                m_session.Filter();
            handled = true;
        }
        if (handled) return VSConstants.S_OK;
        return retVal;
    }
    
  6. 下列程式碼是觸發程序完成的工作階段的私用方法。

    Private Function TriggerCompletion() As Boolean 
        'the caret must be in a non-projection location  
        Dim caretPoint As SnapshotPoint? = m_textView.Caret.Position.Point.GetPoint(Function(textBuffer) ((Not textBuffer.ContentType.IsOfType("projection"))), PositionAffinity.Predecessor)
        If Not caretPoint.HasValue Then 
            Return False 
        End If
    
        m_session = m_provider.CompletionBroker.CreateCompletionSession(m_textView, caretPoint.Value.Snapshot.CreateTrackingPoint(caretPoint.Value.Position, PointTrackingMode.Positive), True)
    
        'subscribe to the Dismissed event on the session  
        AddHandler m_session.Dismissed, AddressOf OnSessionDismissed
        m_session.Start()
    
        Return True 
    End Function
    
    private bool TriggerCompletion()
    {
        //the caret must be in a non-projection location 
        SnapshotPoint? caretPoint =
        m_textView.Caret.Position.Point.GetPoint(
        textBuffer => (!textBuffer.ContentType.IsOfType("projection")), PositionAffinity.Predecessor);
        if (!caretPoint.HasValue)
        {
            return false;
        }
    
        m_session = m_provider.CompletionBroker.CreateCompletionSession
     (m_textView,
            caretPoint.Value.Snapshot.CreateTrackingPoint(caretPoint.Value.Position, PointTrackingMode.Positive),
            true);
    
        //subscribe to the Dismissed event on the session 
        m_session.Dismissed += this.OnSessionDismissed;
        m_session.Start();
    
        return true;
    }
    
  7. 下列程式碼是從取消訂閱的私用方法Dismissed事件。

    Private Sub OnSessionDismissed(ByVal sender As Object, ByVal e As EventArgs)
        RemoveHandler m_session.Dismissed, AddressOf OnSessionDismissed
        m_session = Nothing 
    End Sub
    
    private void OnSessionDismissed(object sender, EventArgs e)
    {
        m_session.Dismissed -= this.OnSessionDismissed;
        m_session = null;
    }
    

建置和測試程式碼

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

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

  1. 建置方案。

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

  3. 建立文字檔案,然後鍵入一些文字以包含字 [新增]。

  4. 當您第一次輸入"a"和接著 「 d 的 」,應該會顯示包含 「 新增 」 和 「 調整 」 的清單。 請注意已選取 [加入。 當您輸入另一個"d"時,清單應只"新增",其中已選取。 您可以藉由按下空格鍵、 TAB 或 ENTER,確認 「 加入 」 或關閉輸入 esc 鍵或其他任何字元的清單。

請參閱

工作

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