Compartir a través de


tutorial: Mostrar la finalización de instrucciones

Puede implementar características basadas en el lenguaje como la finalización de instrucciones definiendo los identificadores para los que desea proporcionar la finalización, y después desencadenando una sesión de finalización. Puede definir la finalización de instrucciones en el contexto de un servicio de, o puede definir dispone de la extensión de nombre de archivo y tipo de contenido, y finalización de la pantalla sólo para ese tipo, o puede desencadenar la finalización para un tipo de contenido existente (como “texto simple”). Este tutorial muestra cómo activar la finalización de instrucciones para el tipo de contenido de “texto simple”, que es el tipo de contenido de archivos de texto. El tipo de contenido “text” es el antecesor del resto de los tipos de contenido, incluido el código y archivos XML.

La finalización de instrucciones se activan normalmente escribiendo ciertos caracteres, por ejemplo, escribiendo el principio de un identificador como “utilizando”. Es despedida normalmente al presionar la BARRA ESPACIADORA, TAB, o ENTRAR para confirmar una selección. Las características de IntelliSense que son desencadenadas escribiendo un carácter se pueden implementar mediante un controlador de comandos por presiones de tecla (la interfaz de IOleCommandTarget ) y un proveedor de controlador que implementa la interfaz de IVsTextViewCreationListener . Para crear el origen de finalización, que es la lista de identificadores que participan en la finalización, implemente la interfaz y un proveedor de origen de finalización (la interfaz de ICompletionSource de ICompletionSourceProvider ). Los proveedores son elementos (MEF) de managed extensibility framework, y son responsables de exportar el origen y las clases de controlador e importar los servicios y los agentes, por ejemplo, ITextStructureNavigatorSelectorService, que permite navegar en el búfer de texto, y ICompletionBroker, que activa en la sesión de finalización.

Este tutorial muestra cómo implementar la finalización de instrucciones para un conjunto codificadas de forma rígida de identificadores. En implementaciones completas, el servicio de lenguaje y documentación de lenguaje son responsables de proporcionar al contenido.

Requisitos previos

Para completar este tutorial, debe instalar Visual Studio 2010 SDK.

Nota

Para obtener más información sobre el SDK de Visual Studio, vea Información general de Visual Studio que extiende.Para averiguar cómo descargar el SDK de Visual Studio, vea Centro para desarrolladores de extensibilidad de Visual Studio en el sitio web de MSDN.

Crear un proyecto MEF

Para crear un proyecto de MEF

  1. Cree un proyecto del clasificador del editor. Llame a la solución CompletionTest.

  2. Abra el archivo source.extension.vsixmanifest del editor de Manifiesto VSIX.

  3. Asegúrese de que la dirección de Contenido contiene un tipo de contenido de Componente MEF y que ruta está establecido en CompletionTest.dll.

  4. Guarde y cierre source.extension.vsixmanifest.

  5. Agregue las referencias siguientes al proyecto y asegúrese de que CopyLocal está establecido en 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. elimine los archivos existentes de la clase.

Implementar el origen de Finalización

El origen de finalización es responsable de obtener el conjunto de identificadores y agregar contenido a la ventana de finalización cuando un usuario un desencadenador de finalización, como las primeras letras de un identificador. En este ejemplo, los identificadores y sus descripciones están incluidos en el código del método deAugmentCompletionSession . En la más real utiliza, puede usar el analizador de lenguaje para obtener los tokens para rellenar la lista de finalización.

Para implementar el origen de finalización

  1. Agregue un archivo de clase y denomínelo TestCompletionSource.

  2. Agregue imports.

    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. modifique la declaración de clase para TestCompletionSource de modo que implemente ICompletionSource.

    Friend Class TestCompletionSource
        Implements ICompletionSource
    
    internal class TestCompletionSource : ICompletionSource
    
  4. Agregue campos privados para el proveedor de origen, el búfer de texto, y una lista de objetos de Completion (que corresponden a los identificadores que participarán en la sesión de finalización).

    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. Agregue un constructor que establezca el proveedor de origen y el búfer. La clase de TestCompletionSourceProvider se define en pasos posteriores.

    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. Implemente el método de AugmentCompletionSession agregando una finalización establecida que contiene las finalizaciones que desea proporcionar en el contexto. Cada conjunto de finalizaciones contiene un conjunto de finalizaciones de Completion , y lo corresponde a una ficha de la ventana de finalización. (En los proyectos de Visual Basic, las fichas de la ventana de finalización se denominan Común y Todo.) el método de FindTokenSpanAtPosition es definido en el paso siguiente.

    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. El método siguiente se utiliza para buscar la palabra actual de la posición del símbolo de intercalación.

    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. implemente el método de 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;
        }
    }
    

Implementar el proveedor de origen de Finalización

El proveedor de origen de finalización es la parte MEF que crea instancias del origen de la finalización.

Para implementar el proveedor de origen de finalización

  1. agregue una clase denominada TestCompletionSourceProvider que implemente ICompletionSourceProvider. Exportar esta clase con ContentTypeAttribute “texto simple” y NameAttribute de “finalizar la prueba”.

    <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. Cantidad ITextStructureNavigatorSelectorService, que debe utilizarse para encontrar la palabra actual en el origen de la finalización.

    <Import()>
    Friend Property NavigatorService() As ITextStructureNavigatorSelectorService
    
    [Import]
    internal ITextStructureNavigatorSelectorService NavigatorService { get; set; }
    
  3. Implemente el método de TryCreateCompletionSource para crear instancias del origen de la finalización.

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

Implementar el proveedor de controlador de comandos de Finalización

El proveedor de controlador de comandos de finalización es derivado de IVsTextViewCreationListener, que está atento un evento de creación de la vista de texto y convierte la vista de IVsTextView (que permite agregar el comando a la cadena de comando del shell de Visual Studio) a ITextView. Puesto que esta clase es una exportación MEF, también puede utilizarla para importar los servicios que se necesiten por el propio controlador de comando.

Para implementar el proveedor de controlador de comandos de finalización

  1. agregue un archivo denominado TestCompletionCommandHandler.

  2. Agregue las instrucciones using siguientes.

    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. agregue una clase denominada TestCompletionHandlerProvider que implemente IVsTextViewCreationListener. Exportar esta clase con NameAttribute “controlador de token de finalización”, ContentTypeAttribute “texto simple”, y TextViewRoleAttribute de Editable.

    <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. Cantidad IVsEditorAdaptersFactoryService, que permite convertir de IVsTextView a ITextView, a ICompletionBroker, y a SVsServiceProvider, que permite obtener acceso a los servicios estándar de 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. Implemente el método de VsTextViewCreated para crear instancias del controlador de comandos.

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

Implementar el controlador de comandos de Finalización

Dado que la finalización de instrucciones se activan por presiones de tecla, debe implementar la interfaz de IOleCommandTarget para recibir y procesar las pulsaciones de tecla que desencadenan, confirmar, y descarta la sesión de finalización.

Para implementar el controlador de comandos de finalización

  1. agregue una clase denominada TestCompletionCommandHandler que implemente IOleCommandTarget.

    Friend Class TestCompletionCommandHandler
        Implements IOleCommandTarget
    
    internal class TestCompletionCommandHandler : IOleCommandTarget
    
  2. Agregue campos privados para el controlador de comando siguiente (al que pasa el comando), la vista de texto, el proveedor de controlador de comandos (que permite obtener acceso a diferentes servicios), y una sesión de finalización.

    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. Agregue un constructor que establezca la vista de texto y campos de proveedor, y agrega el comando a la cadena de comando.

    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. Implemente el método de QueryStatus pasando el comando adelante.

    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. Implemente el método Exec. Cuando este método recibe una tecla, debe realizar una de estas acciones:

    • Permite que el carácter se escribirá en el búfer, y a continuación desencadena o filtrar la finalización (los caracteres de impresión hacen esto).

    • Confirmar la finalización, pero no permiten que el carácter se escribirá en el búfer (el espacio en blanco, TAB, y especifique hacen esto cuando muestran una sesión de finalización).

    • Permite que se superan el comando el controlador siguiente (el resto de los comandos).

    Puesto que este método puede mostrar la interfaz de usuario, debe asegurarse de que no es denominada en un contexto de automatización llamando a 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. El código siguiente es un método privado que desencadena a la sesión de finalización.

    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. El código siguiente es un método privado que cancela la suscripción al evento de 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;
    }
    

Compilar y probar el código

Para probar este código, compile la solución de CompletionTest y ejecútela en la instancia experimental.

para compilar y probar la solución de CompletionTest

  1. Compile la solución.

  2. Al ejecutar este proyecto en el depurador, una segunda instancia de Visual Studio se crea instancias.

  3. Cree un archivo de texto y escriba algún texto que incluya la palabra “agregar”.

  4. Cuando escribe primero “a” y “d”, una lista que contiene la “agregar” y “adaptación” debe mostrar. Observe que la suma es seleccionado. Al escribir otra “d”, la lista debe contener sólo la “agregar”, que selecciona ahora. Puede confirmar la “agregar” presione la BARRA ESPACIADORA, TAB, o ENTRAR, o descarta la lista escribiendo ESC o cualquier otro carácter.

Vea también

Tareas

tutorial: vincular un tipo de contenido a una extensión de nombre de archivo