Freigeben über


Exemplarische Vorgehensweise: Anweisungsvervollständigung anzeigen

Sie können LANGUAGE-basierte Funktionen wie Anweisungsvervollständigung implementieren, indem Sie die ID definieren, für die Sie bereitstellen möchten, schließen und anschließend eine Vervollständigungssitzung gestartet. Sie können die Anweisungsvervollständigung im Kontext des Sprachdiensts definieren, oder Sie können definieren, Dateinamenerweiterung und Inhaltstyp und Anzeigen abschluss nur für diesen Typ besitzen, oder Sie können Vervollständigung für einen vorhandenen Inhaltstyp starten (z. B. „Klartext“). In dieser exemplarischen Vorgehensweise wird erläutert, wie Anweisungsvervollständigung für den Inhaltstyp“ Klartext „, startet der Inhaltstyp von Textdateien ist. Der „Text“ Inhaltstyp ist der übergeordneten Elemente aller anderen Inhaltstypen, einschließlich Code und XML-Dateien.

Anweisungsvervollständigung wird in der Regel ausgelöst, indem bestimmte Zeichen eingibt, z. B. mit dem Anfang eines Bezeichners z. B. „using“ wechselt. Es ist i geschlossen, indem Sie die LEERTASTE, die TAB- oder EINGABETASTE drückt, um die Auswahl zu bestätigen. IntelliSense-Features, die gestartet werden, indem ein Zeichen eingibt, können implementiert werden, indem ein Befehlshandler für die Tastatureingaben (die IOleCommandTarget-Schnittstelle) und einen Handler für IVsTextViewCreationListener verwendet, der die Schnittstelle implementiert. Um die Vervollständigung Quelle zu erstellen, die die Liste mit Bezeichnern ist die am Abschluss beteiligt sind, implementieren Sie die ICompletionSource-Schnittstelle und einen abschließenden quellanbieter (die ICompletionSourceProvider-Schnittstelle). Diese Anbieter sind Komponenten des Managed Extensibility Framework (MEF) und zum Exportieren der Quell- und Controllerklassen und das Importieren von Diensten und Brokern z. B. ITextStructureNavigatorSelectorService, das Sie im Textpuffer navigieren können, und ICompletionBroker, das die Vervollständigungssitzung gestartet wird.

In dieser exemplarischen Vorgehensweise wird erläutert, wie Anweisungsvervollständigung für einen hartcodierten Satz Bezeichner implementiert. In den vollständigen Implementierungen sind der Sprachdienst und in der Dokumentation zur Sprache zum Bereitstellen dieses Inhalts verantwortlich.

Vorbereitungsmaßnahmen

Zum Abschließen dieser exemplarischen Vorgehensweise müssen Sie Visual Studio 2010 SDKinstallieren.

Hinweis

Weitere Informationen über das Visual Studio-SDK finden Sie unter Erweitern von Visual Studio Overview.Um herauszufinden finden Sie unter wie das Visual Studio-SDK, auf Visual Studio Extensibility Developer Center der MSDN-Website herunterlädt.

Ein MEF-Projekt erstellen

So erstellen Sie ein MEF-Projekt

  1. Erstellen Sie ein Projekt Editor-Klassifizierungs. Geben Sie der Projektmappe CompletionTest.

  2. Öffnen Sie die Datei source.extension.vsixmanifest im VSIX-Manifest-Editor.

  3. Überprüfen Sie, ob die Inhalt Überschrift einen MEF-Komponente Inhaltstyp enthält und dass Pfad zu CompletionTest.dllfestgelegt ist.

  4. Speichern und schließen Sie source.extension.vsixmanifest.

  5. Fügen Sie dem Projekt die folgenden Verweise hinzu und überprüfen Sie, ob CopyLocal zu falsefestgelegt ist:

    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. Löschen Sie die vorhandenen Klassendateien.

Die Abschluss-Quelle implementieren

Die Vervollständigung Quelle ist zum Erfassen des Satzes der Bezeichner und zum Hinzufügen von Inhalt für den Abschluss wenn Benutzer ein Fenster schließen ", wie die ersten Buchstaben eines Bezeichners. In diesem Beispiel werden die ID und ihre Beschreibungen in derAugmentCompletionSession-Methode hartcodiert. In realstem verwendet, verwenden Sie den Parser der Sprache, um die Token abrufen, um die Vervollständigungsliste aufzufüllen.

So schließen Sie die Quelle implementieren

  1. Fügen Sie eine Klassendatei hinzu, und nennen Sie sie TestCompletionSource.

  2. Fügen Sie die folgenden Importe hinzu.

    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. Ändern Sie die Klassendeklaration für TestCompletionSource , sodass es ICompletionSourceimplementiert.

    Friend Class TestCompletionSource
        Implements ICompletionSource
    
    internal class TestCompletionSource : ICompletionSource
    
  4. Fügen Sie private Felder für den Quellanbieter, den Textpuffer und eine Liste von Completion-Objekten (die den Bezeichnern entsprechen, die an der Vervollständigungssitzung beteiligt sind).

    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. Fügen Sie einen Konstruktor hinzu, mit dem der Quellanbieter und des Puffers festlegt. Die TestCompletionSourceProvider-Klasse wird in späteren Schritten definiert.

    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. Implementieren Sie die AugmentCompletionSession-Methode, indem Sie einen festgelegten Schließen hinzufügen, die die Vervollständigungen, die Sie im Kontext bereitstellen möchten. Jeder Vervollständigungssatz enthält einen Satz Completion von Abschlüssen und entspricht einer Registerkarte des Fensters Schließen. (In Visual Basic-Projekten Fenster schließen, werden die Registerkarten Allgemein und AlleNamen). Die FindTokenSpanAtPositions-Methode wird im nächsten Schritt definiert.

    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. Die folgende Methode wird verwendet, um das aktuelle Wort an der Position des Caretzeichens zu suchen.

    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. Implementieren Sie die Dispose()-Methode:

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

Implementieren des Abschluss-Quellanbieter

Der Abschluss quellanbieter ist der MEF-Komponenten-Teil, der die Quelle des vollständig instanziiert.

So schließen quellanbieter implementieren

  1. Fügen Sie eine Klasse hinzu, die TestCompletionSourceProvider , die ICompletionSourceProviderimplementiert. Exportieren Sie diese Klasse mit ContentTypeAttribute „des Klartextes NameAttribute “ und „Test“ abschlusses.

    <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. Importieren Sie ITextStructureNavigatorSelectorService, das verwendet werden soll, um das aktuelle Wort an der Quelle Abschluss zu suchen.

    <Import()>
    Friend Property NavigatorService() As ITextStructureNavigatorSelectorService
    
    [Import]
    internal ITextStructureNavigatorSelectorService NavigatorService { get; set; }
    
  3. Implementieren Sie die TryCreateCompletionSource-Methode, um den Abschluss Quelle zu instanziieren.

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

Implementieren des Abschluss-Befehls-Handler-Anbieter

Der Anbieter ist der befehls-Handler Schließen IVsTextViewCreationListenerabgeleitet, der auf ein Ereignis überwacht ansichts-Erstellungs Text und die Ansicht von IVsTextView (die den Befehl ermöglicht, die Befehlskette der Visual Studio-Shells hinzugefügt werden soll ITextView) konvertiert. Da diese Klasse einen MEF-Export ist, können Sie ihn auch verwenden, um die Dienste zu importieren, die vom Befehlshandler selbst benötigt werden.

So schließen befehls-Handler implementieren Anbieter

  1. Fügen Sie eine Datei hinzufügen, die TestCompletionCommandHandler benannt ist.

  2. Fügen Sie die folgenden using-Anweisungen hinzu.

    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. Fügen Sie eine Klasse hinzu, die TestCompletionHandlerProvider , die IVsTextViewCreationListenerimplementiert. Exportieren Sie diese Klasse mit NameAttribute „des Tokens abschluss handlers“, „ ContentTypeAttribute des Klartextes“ und TextViewRoleAttribute von 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. Importieren Sie IVsEditorAdaptersFactoryService, auf die Sie von IVsTextView zu ITextView, ICompletionBrokerund SVsServiceProviderkonvertieren können Sie die Standardeinstellung. studio-Dienstleistungen visual Zugriff zulässig.

    <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. Implementieren Sie die VsTextViewCreated-Methode, um den Befehlshandler zu instanziieren.

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

Implementieren des Abschluss-Befehls-Handler

Da die Anweisungsvervollständigung von Tastatureingaben gestartet wird, müssen Sie die IOleCommandTarget-Schnittstelle implementieren, um die Tastatureingaben zu empfangen und zu verarbeiten, die die Vervollständigungssitzung gestartet, einen Commit als auch zurückweisen.

Um den Befehl Schließen Klassenhandler implementieren

  1. Fügen Sie eine Klasse hinzu, die TestCompletionCommandHandler , die IOleCommandTargetimplementiert.

    Friend Class TestCompletionCommandHandler
        Implements IOleCommandTarget
    
    internal class TestCompletionCommandHandler : IOleCommandTarget
    
  2. Fügen Sie private Felder für den nächsten Befehlshandler (welcher Sie den Befehl übergeben), die Textansicht, den Befehlshandler (Hersteller der es Ihnen ermöglicht, unterschiedliche Dienste zuzugreifen) und eine Vervollständigungssitzung hinzu.

    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. Fügen Sie einen Konstruktor, der die Textansicht und die Anbieter Feldern festlegen, den Befehl hinzu und fügt die Befehlskette hinzu.

    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. Implementieren Sie die QueryStatus-Methode, indem Sie für den Befehl übergeben.

    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. Implementieren Sie die Exec-Methode. Wenn diese Methode eine Tastatureingabe empfängt, muss sie eine dieser Schritte ausführen:

    • Lassen Sie das Zeichen in den Puffer geschrieben werden soll, und starten Sie dann oder filtern Sie hierfür Drucksteuerzeichen Close ().

    • Führen Sie den Abschluss eines Commit ausgeführt, jedoch können Sie keine Zeichen in den Puffer geschrieben werden soll (Leerräume TAB und EINGABETASTE hierfür, wenn eine Vervollständigungssitzung angezeigt wird).

    • Lassen Sie den Befehl, um zum nächsten Handler (alle anderen Befehlen) übergeben werden sollen.

    Da diese Methode möglicherweise Benutzeroberfläche angezeigt wird, sollten Sie überprüfen, ob es über nicht in einem Kontext aufgerufen wird, indem Sie IsInAutomationFunctionaufrufen.

    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. Der folgende Code ist eine private Methode, die die Vervollständigungssitzung gestartet wird.

    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. Der folgende Code ist eine private Methode, die vom Ereignis Dismissed kündigt.

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

Erstellen und Testen von Code

Um diesen Code zu testen, erstellen Sie die CompletionTest-Projektmappe und führen Sie sie in der experimentellen Instanz aus.

So erstellen und testen die CompletionTest-Projektmappe

  1. Erstellen Sie die Projektmappe.

  2. Wenn Sie dieses Projekt im Debugger ausführen, wird eine zweite Instanz von Visual Studio instanziiert.

  3. Erstellen Sie eine Textdatei, und geben Sie Text ein, der das Wort „Hinzufügen“ enthält.

  4. Da Sie zunächst „a“ und dann „d“ eingeben, sollte eine Liste mit „Hinzufügen“ und „Anpassung“ angezeigt werden. Beachten Sie, dass zusätzlich ausgewählt ist. Wenn Sie ein weiteres „d“ eingeben, sollte die Liste nur „Zusatz“ enthalten, die jetzt ausgewählt ist. Sie können „Zusatz“ übernehmen, indem Sie die LEERTASTE, die TAB- oder EINGABETASTE drücken, oder weisen Sie die Liste, indem Sie ESC oder ein beliebiges anderes Zeichen eingegeben werden.

Siehe auch

Aufgaben

Exemplarische Vorgehensweise: Verknüpfen einer Dateinamenerweiterung eines Inhaltstyps