Exemplarische Vorgehensweise: Unterzeichnungs-Hilfe anzeigen
Signatur-Hilfe (auch als Parameter) wird die Signatur einer Methode in einer QuickInfo wenn Benutzer das Parameterlisten anfangs Zeichen an (in der Regel eine öffnende Klammer). Während ein Parameter und ein Trennzeichen (in der Regel ein Komma) eingegeben werden, wird die QuickInfo aktualisiert, um den nächsten Parameter in Fettschrift anzuzeigen. Sie können Unterzeichnungs-Hilfe im Kontext eines Sprachdiensts definieren, oder Sie können definieren, Erweiterung und Inhaltstyp und Anzeige Unterzeichnungs-Hilfe nur für diesen Typ besitzen, oder Sie können Unterzeichnungs-Hilfe nach einem vorhandenen Inhaltstyp (z. B. „text“ angezeigt). In dieser exemplarischen Vorgehensweise wird erläutert, wie Unterzeichnungs-Hilfe für den Inhaltstyp „text“ anzeigt.
Signatur-Hilfe wird in der Regel ausgelöst, indem ein bestimmtes Zeichen eingibt, z. B. „öffnende Klammer ((“) und Schließen von das Eingeben eines anderen Zeichens z. B. " ()“ schließenden Klammer). 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. Zum Erstellen der Signatur können Sie die Quelle, die Unterschriftenliste ist das eine Verbindung mit der Unterzeichnungs-Hilfe beteiligt sind, implementieren die ISignatureHelpSource Quellanbieter und eine Schnittstelle ISignatureHelpSourceProvider der die Schnittstelle implementiert. 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 ISignatureHelpBroker, das die Unterzeichnungs-Hilfe eine gestartet wird.
In dieser exemplarischen Vorgehensweise wird erläutert, wie Unterzeichnungs-Hilfe für einen hartcodierten Satz Bezeichner implementiert. In den vollständigen Implementierungen ist die 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
Erstellen Sie ein Projekt Editor-Klassifizierungs. Geben Sie der Projektmappe SignatureHelpTest.
Öffnen Sie die Source.extension.vsixmanifest-Datei im VSIX-Manifest-Editor.
Überprüfen Sie, ob die Content Überschrift einen MEF-Komponenten-Inhaltstyp enthält und dass Path zu SignatureHelpTest.dll festgelegt ist.
Speichern und schließen Sie Source.extension.vsixmanifest.
Fügen Sie dem Projekt die folgenden Verweise hinzu: falsefestlegen und CopyLocal
Microsoft.VisualStudio.Editor
Microsoft.VisualStudio.Language.Intellisense
Microsoft.VisualStudio.OLE.Interop
Microsoft.VisualStudio.Shell
Microsoft.VisualStudio.TextManager.Interop
Löschen Sie die vorhandenen Klassendateien.
Unterzeichnungs-Hilfe-Unterzeichnungen implementieren und Parametern
Die Quelle des Unterzeichnungs-Hilfe basiert auf Signaturen, die ISignatureimplementieren, von denen jedes Parameter enthält, die IParameterimplementieren. In einer vollständigen Implementierung würde diese Informationen in der Dokumentation zur Sprache abgerufen, aber in diesem Beispiel werden die Signaturen hartcodiert.
Um die Signatur beim Implementieren von Signaturen und Parametern
Fügen Sie eine Klassendatei hinzu, und nennen Sie sie SignatureHelpSource.
Fügen Sie die folgenden Importe hinzu.
Imports System Imports System.Collections.Generic Imports System.Linq Imports System.Text Imports System.Collections.ObjectModel Imports System.ComponentModel.Composition Imports System.Runtime.InteropServices Imports Microsoft.VisualStudio.Language.Intellisense Imports Microsoft.VisualStudio.Text Imports Microsoft.VisualStudio.Text.Editor Imports Microsoft.VisualStudio.Utilities Imports Microsoft.VisualStudio.Editor Imports Microsoft.VisualStudio.Text.Operations Imports Microsoft.VisualStudio Imports Microsoft.VisualStudio.TextManager.Interop Imports Microsoft.VisualStudio.OLE.Interop
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel.Composition; using System.Runtime.InteropServices; using Microsoft.VisualStudio.Language.Intellisense; using Microsoft.VisualStudio.Text; using Microsoft.VisualStudio.Text.Editor; using Microsoft.VisualStudio.Utilities; using Microsoft.VisualStudio.Editor; using Microsoft.VisualStudio.Text.Operations; using Microsoft.VisualStudio; using Microsoft.VisualStudio.TextManager.Interop; using Microsoft.VisualStudio.OLE.Interop;
Fügen Sie eine Klasse hinzu, die TestParameter , die IParameterimplementiert.
Friend Class TestParameter Implements IParameter
internal class TestParameter : IParameter
Fügen Sie einen Konstruktor hinzu, der alle Eigenschaften festgelegt werden.
Public Sub New(ByVal documentation As String, ByVal locus As Span, ByVal name As String, ByVal signature As ISignature) Me.privateDocumentation = documentation Me.privateLocus = locus Me.privateName = name Me.privateSignature = signature End Sub
public TestParameter(string documentation, Span locus, string name, ISignature signature) { Documentation = documentation; Locus = locus; Name = name; Signature = signature; }
Fügen Sie die Eigenschaften von IParameterhinzu.
Private privateDocumentation As String ReadOnly Property Documentation() As String Implements IParameter.Documentation Get Return privateDocumentation End Get End Property Private privateLocus As Span ReadOnly Property Locus() As Span Implements IParameter.Locus Get Return privateLocus End Get End Property Private privateName As String ReadOnly Property Name() As String Implements IParameter.Name Get Return privateName End Get End Property Private privateSignature As ISignature ReadOnly Property Signature() As ISignature Implements IParameter.Signature Get Return privateSignature End Get End Property Private privatePrettyPrintedLocus As Span ReadOnly Property PrettyPrintedLocus() As Span Implements IParameter.PrettyPrintedLocus Get Return privatePrettyPrintedLocus End Get End Property
public string Documentation { get; private set; } public Span Locus { get; private set; } public string Name { get; private set; } public ISignature Signature { get; private set; } public Span PrettyPrintedLocus { get; private set; }
Fügen Sie eine Klasse hinzu, die TestSignature , die ISignatureimplementiert.
Friend Class TestSignature Implements ISignature
internal class TestSignature : ISignature
Fügen Sie einige private Felder hinzu.
Private m_subjectBuffer As ITextBuffer Private m_currentParameter As IParameter Private m_content As String Private m_documentation As String Friend m_applicableToSpan As ITrackingSpan Friend m_parameters As ReadOnlyCollection(Of IParameter) Private m_printContent As String
private ITextBuffer m_subjectBuffer; private IParameter m_currentParameter; private string m_content; private string m_documentation; private ITrackingSpan m_applicableToSpan; private ReadOnlyCollection<IParameter> m_parameters; private string m_printContent;
Fügen Sie einen Konstruktor hinzu, der die Felder festlegen und Changed das Ereignis abonniert.
Friend Sub New(ByVal subjectBuffer As ITextBuffer, ByVal content As String, ByVal doc As String, ByVal parameters As ReadOnlyCollection(Of IParameter)) m_subjectBuffer = subjectBuffer m_content = content m_documentation = doc m_parameters = parameters AddHandler m_subjectBuffer.Changed, AddressOf OnSubjectBufferChanged End Sub
internal TestSignature(ITextBuffer subjectBuffer, string content, string doc, ReadOnlyCollection<IParameter> parameters) { m_subjectBuffer = subjectBuffer; m_content = content; m_documentation = doc; m_parameters = parameters; m_subjectBuffer.Changed += new EventHandler<TextContentChangedEventArgs>(OnSubjectBufferChanged); }
Deklarieren Sie ein CurrentParameterChanged-Ereignis. Dieses Ereignis wird ausgelöst, wenn der Benutzer einen der Parameter in der Signatur ausfüllt.
Public Event CurrentParameterChanged As EventHandler(Of CurrentParameterChangedEventArgs) Implements ISignature.CurrentParameterChanged
public event EventHandler<CurrentParameterChangedEventArgs> CurrentParameterChanged;
Implementieren Sie die CurrentParameter-Eigenschaft, sodass sie das CurrentParameterChanged-Ereignis auslöst, wenn der Eigenschaftswert geändert wird.
ReadOnly Property CurrentParameter() As IParameter Implements ISignature.CurrentParameter Get Return m_currentParameter End Get End Property
public IParameter CurrentParameter { get { return m_currentParameter; } internal set { if (m_currentParameter != value) { IParameter prevCurrentParameter = m_currentParameter; m_currentParameter = value; this.RaiseCurrentParameterChanged(prevCurrentParameter, m_currentParameter); } } }
Fügen Sie eine Methode hinzu, die das CurrentParameterChanged-Ereignis auslöst.
Private Sub RaiseCurrentParameterChanged(ByVal prevCurrentParameter As IParameter, ByVal newCurrentParameter As IParameter) Dim tempHandler As EventHandler(Of CurrentParameterChangedEventArgs) = Me.CurrentParameterChangedEvent If tempHandler IsNot Nothing Then tempHandler(Me, New CurrentParameterChangedEventArgs(prevCurrentParameter, newCurrentParameter)) End If End Sub
private void RaiseCurrentParameterChanged(IParameter prevCurrentParameter, IParameter newCurrentParameter) { EventHandler<CurrentParameterChangedEventArgs> tempHandler = this.CurrentParameterChanged; if (tempHandler != null) { tempHandler(this, new CurrentParameterChangedEventArgs(prevCurrentParameter, newCurrentParameter)); } }
Fügen Sie eine Methode hinzu, die den aktuellen Parameter berechnet, indem die Anzahl von Kommas und der Anzahl der in ApplicableToSpan Kommas in der Signatur überprüft.
Friend Sub ComputeCurrentParameter() If Parameters.Count = 0 Then Me.m_currentParameter = Nothing Return End If 'the number of commas in the string is the index of the current parameter Dim sigText As String = ApplicableToSpan.GetText(m_subjectBuffer.CurrentSnapshot) Dim currentIndex As Integer = 0 Dim commaCount As Integer = 0 Do While currentIndex < sigText.Length Dim commaIndex As Integer = sigText.IndexOf(","c, currentIndex) If commaIndex = -1 Then Exit Do End If commaCount += 1 currentIndex = commaIndex + 1 Loop If commaCount < Parameters.Count Then Me.m_currentParameter = Parameters(commaCount) Else 'too many commas, so use the last parameter as the current one. Me.m_currentParameter = Parameters(Parameters.Count - 1) End If End Sub
internal void ComputeCurrentParameter() { if (Parameters.Count == 0) { this.CurrentParameter = null; return; } //the number of commas in the string is the index of the current parameter string sigText = ApplicableToSpan.GetText(m_subjectBuffer.CurrentSnapshot); int currentIndex = 0; int commaCount = 0; while (currentIndex < sigText.Length) { int commaIndex = sigText.IndexOf(',', currentIndex); if (commaIndex == -1) { break; } commaCount++; currentIndex = commaIndex + 1; } if (commaCount < Parameters.Count) { this.CurrentParameter = Parameters[commaCount]; } else { //too many commas, so use the last parameter as the current one. this.CurrentParameter = Parameters[Parameters.Count - 1]; } }
Fügen Sie einen Ereignishandler für das Changed-Ereignis hinzu, das die ComputeCurrentParameter()-Methode aufruft.
Friend Sub OnSubjectBufferChanged(ByVal sender As Object, ByVal e As TextContentChangedEventArgs) Me.ComputeCurrentParameter() End Sub
internal void OnSubjectBufferChanged(object sender, TextContentChangedEventArgs e) { this.ComputeCurrentParameter(); }
Implementieren Sie die ApplicableToSpan-Eigenschaft. Diese Eigenschaft enthält ITrackingSpan an, die mit dem Textabschnitt im Puffer entspricht, auf dem die Signatur gültig ist.
ReadOnly Property ApplicableToSpan() As ITrackingSpan Implements ISignature.ApplicableToSpan Get Return (m_applicableToSpan) End Get End Property
public ITrackingSpan ApplicableToSpan { get { return (m_applicableToSpan); } internal set { m_applicableToSpan = value; } }
Implementieren Sie die anderen Parameter.
ReadOnly Property Content() As String Implements ISignature.Content Get Return (m_content) End Get End Property ReadOnly Property Documentation() As String Implements ISignature.Documentation Get Return (m_documentation) End Get End Property ReadOnly Property Parameters() As ReadOnlyCollection(Of IParameter) Implements ISignature.Parameters Get Return (m_parameters) End Get End Property ReadOnly Property PrettyPrintedContent() As String Implements ISignature.PrettyPrintedContent Get Return (m_printContent) End Get End Property
public string Content { get { return (m_content); } internal set { m_content = value; } } public string Documentation { get { return (m_documentation); } internal set { m_documentation = value; } } public ReadOnlyCollection<IParameter> Parameters { get { return (m_parameters); } internal set { m_parameters = value; } } public string PrettyPrintedContent { get { return (m_printContent); } internal set { m_printContent = value; } }
Die Unterzeichnungs-Hilfe-Quelle implementieren
Die Quelle des Unterzeichnungs-Hilfe ist der Satz von Signaturen, zu der Informationen bereitstellen.
So geben Sie die Quelle Unterzeichnungs-Hilfe Implementieren
Fügen Sie eine Klasse hinzu, die TestSignatureHelpSource , die ISignatureHelpSourceimplementiert.
Friend Class TestSignatureHelpSource Implements ISignatureHelpSource
internal class TestSignatureHelpSource : ISignatureHelpSource
Fügen Sie einen Verweis auf den Textpuffer eingefügt.
Private m_textBuffer As ITextBuffer
private ITextBuffer m_textBuffer;
Fügen Sie einen Konstruktor hinzu, der den Textpuffer und den Unterzeichnungs-Hilfequellanbieter festlegt.
Public Sub New(ByVal textBuffer As ITextBuffer) m_textBuffer = textBuffer End Sub
public TestSignatureHelpSource(ITextBuffer textBuffer) { m_textBuffer = textBuffer; }
Implementieren Sie die AugmentSignatureHelpSession-Methode. In diesem Beispiel werden die Signaturen hartcodiert, aber in einer vollständigen Implementierung würden Sie diese Informationen in der Dokumentation zur Sprache ab.
Public Sub AugmentSignatureHelpSession(ByVal session As ISignatureHelpSession, ByVal signatures As IList(Of ISignature)) Implements ISignatureHelpSource.AugmentSignatureHelpSession Dim snapshot As ITextSnapshot = m_textBuffer.CurrentSnapshot Dim position As Integer = session.GetTriggerPoint(m_textBuffer).GetPosition(snapshot) Dim applicableToSpan As ITrackingSpan = m_textBuffer.CurrentSnapshot.CreateTrackingSpan(New Span(position, 0), SpanTrackingMode.EdgeInclusive, 0) signatures.Add(CreateSignature(m_textBuffer, "add(int firstInt, int secondInt)", "Documentation for adding integers.", applicableToSpan)) signatures.Add(CreateSignature(m_textBuffer, "add(double firstDouble, double secondDouble)", "Documentation for adding doubles.", applicableToSpan)) End Sub
public void AugmentSignatureHelpSession(ISignatureHelpSession session, IList<ISignature> signatures) { ITextSnapshot snapshot = m_textBuffer.CurrentSnapshot; int position = session.GetTriggerPoint(m_textBuffer).GetPosition(snapshot); ITrackingSpan applicableToSpan = m_textBuffer.CurrentSnapshot.CreateTrackingSpan( new Span(position, 0), SpanTrackingMode.EdgeInclusive, 0); signatures.Add(CreateSignature(m_textBuffer, "add(int firstInt, int secondInt)", "Documentation for adding integers.", applicableToSpan)); signatures.Add(CreateSignature(m_textBuffer, "add(double firstDouble, double secondDouble)", "Documentation for adding doubles.", applicableToSpan)); }
Die Hilfsmethode CreateSignature() wird nur zur Veranschaulichung bereitgestellt.
Private Function CreateSignature(ByVal textBuffer As ITextBuffer, ByVal methodSig As String, ByVal methodDoc As String, ByVal span As ITrackingSpan) As TestSignature Dim sig As New TestSignature(textBuffer, methodSig, methodDoc, Nothing) AddHandler textBuffer.Changed, AddressOf sig.OnSubjectBufferChanged 'find the parameters in the method signature (expect methodname(one, two) Dim pars() As String = methodSig.Split(New Char() {"("c, ","c, ")"c}) Dim paramList As New List(Of IParameter)() Dim locusSearchStart As Integer = 0 For i As Integer = 1 To pars.Length - 1 Dim param As String = pars(i).Trim() If String.IsNullOrEmpty(param) Then Continue For End If 'find where this parameter is located in the method signature Dim locusStart As Integer = methodSig.IndexOf(param, locusSearchStart) If locusStart >= 0 Then Dim locus As New Span(locusStart, param.Length) locusSearchStart = locusStart + param.Length paramList.Add(New TestParameter("Documentation for the parameter.", locus, param, sig)) End If Next i sig.m_Parameters = New ReadOnlyCollection(Of IParameter)(paramList) sig.m_ApplicableToSpan = span sig.ComputeCurrentParameter() Return sig End Function
private TestSignature CreateSignature(ITextBuffer textBuffer, string methodSig, string methodDoc, ITrackingSpan span) { TestSignature sig = new TestSignature(textBuffer, methodSig, methodDoc, null); textBuffer.Changed += new EventHandler<TextContentChangedEventArgs>(sig.OnSubjectBufferChanged); //find the parameters in the method signature (expect methodname(one, two) string[] pars = methodSig.Split(new char[] { '(', ',', ')' }); List<IParameter> paramList = new List<IParameter>(); int locusSearchStart = 0; for (int i = 1; i < pars.Length; i++) { string param = pars[i].Trim(); if (string.IsNullOrEmpty(param)) continue; //find where this parameter is located in the method signature int locusStart = methodSig.IndexOf(param, locusSearchStart); if (locusStart >= 0) { Span locus = new Span(locusStart, param.Length); locusSearchStart = locusStart + param.Length; paramList.Add(new TestParameter("Documentation for the parameter.", locus, param, sig)); } } sig.Parameters = new ReadOnlyCollection<IParameter>(paramList); sig.ApplicableToSpan = span; sig.ComputeCurrentParameter(); return sig; }
Implementieren Sie die GetBestMatch-Methode. In diesem Beispiel gibt es nur zwei Signaturen, von denen jede zwei Parameter verfügt. Daher ist diese Methode nicht erforderlich. In einer volleren mehr als eine Implementierung in der Quelle Unterzeichnungs-Hilfe verfügbar ist, wird diese Methode verwendet, um zu entscheiden, ob die höchste Priorität Unterzeichnungs-Hilfe Quelle einer übereinstimmenden Signatur angeben kann. Wenn dies nicht möglich ist, gibt die Methode NULL zurück und NEXT-hoch Priorität Quelle wird aufgefordert, eine Übereinstimmung zu erzielen.
Public Function GetBestMatch(ByVal session As ISignatureHelpSession) As ISignature Implements ISignatureHelpSource.GetBestMatch If session.Signatures.Count > 0 Then Dim applicableToSpan As ITrackingSpan = session.Signatures(0).ApplicableToSpan Dim text As String = applicableToSpan.GetText(applicableToSpan.TextBuffer.CurrentSnapshot) If text.Trim().Equals("add") Then 'get only "add" Return session.Signatures(0) End If End If Return Nothing End Function
public ISignature GetBestMatch(ISignatureHelpSession session) { if (session.Signatures.Count > 0) { ITrackingSpan applicableToSpan = session.Signatures[0].ApplicableToSpan; string text = applicableToSpan.GetText(applicableToSpan.TextBuffer.CurrentSnapshot); if (text.Trim().Equals("add")) //get only "add" return session.Signatures[0]; } return null; }
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 Unterzeichnungs-Hilfe-Quellanbieter
Der Unterzeichnungs-Hilfe quellanbieter ist zum Exportieren der Komponente des Managed Extensibility Framework (MEF) und zum Instanziieren der Quelle Unterzeichnungs-Hilfe verantwortlich.
So implementieren quellanbieter Unterzeichnungs-Hilfe
Fügen Sie eine Klasse hinzu, die TestSignatureHelpSourceProvider benannt wird, die ISignatureHelpSourceProviderimplementiert, und exportieren Sie sie mit NameAttribute, ContentTypeAttribute „des Texts“ und OrderAttribute von Before= " default“.
<Export(GetType(ISignatureHelpSourceProvider)), Name("Signature Help source"), Order(Before:="default"), ContentType("text")> Friend Class TestSignatureHelpSourceProvider Implements ISignatureHelpSourceProvider
[Export(typeof(ISignatureHelpSourceProvider))] [Name("Signature Help source")] [Order(Before = "default")] [ContentType("text")] internal class TestSignatureHelpSourceProvider : ISignatureHelpSourceProvider
Implementieren Sie TryCreateSignatureHelpSource , indem Sie TestSignatureHelpSourceinstanziieren.
Public Function TryCreateSignatureHelpSource(ByVal textBuffer As ITextBuffer) As ISignatureHelpSource Implements ISignatureHelpSourceProvider.TryCreateSignatureHelpSource Return New TestSignatureHelpSource(textBuffer) End Function
public ISignatureHelpSource TryCreateSignatureHelpSource(ITextBuffer textBuffer) { return new TestSignatureHelpSource(textBuffer); }
Implementieren des Befehls-Handler
Signatur-Hilfe wird normalerweise von A gestartet (Zeichen und geschlossenes von A) Zeichen. Sie können diese verarbeiten Tastatureingaben, indem Sie IOleCommandTarget implementieren, damit dies eine Unterzeichnungs-Hilfe eine startet, wenn er A erhält (das Zeichen, das von einem bekannten Methodennamen vorangestellt ist, und weist die Sitzung zurück, wenn A) empfängt.
So implementieren Sie den Befehlshandler
Fügen Sie eine Klasse hinzu, die TestSignatureHelpCommand , die IOleCommandTargetimplementiert.
Friend NotInheritable Class TestSignatureHelpCommandHandler Implements IOleCommandTarget
internal sealed class TestSignatureHelpCommandHandler : IOleCommandTarget
Fügen Sie private Felder für den IVsTextView Adapter (der Sie den Befehlshandler dem Instanzenweg Handler hinzufügen können), die Textansicht, der Unterzeichnungs-Hilfe Broker und - Sitzung, und ITextStructureNavigatorfolgenden IOleCommandTargethinzu.
Private m_nextCommandHandler As IOleCommandTarget Private m_textView As ITextView Private m_broker As ISignatureHelpBroker Private m_session As ISignatureHelpSession Private m_navigator As ITextStructureNavigator
IOleCommandTarget m_nextCommandHandler; ITextView m_textView; ISignatureHelpBroker m_broker; ISignatureHelpSession m_session; ITextStructureNavigator m_navigator;
Fügen Sie einen Konstruktor, um diese Felder hinzu und initialisiert den Filter den Filter Instanzenweg Befehl hinzuzufügen.
Friend Sub New(ByVal textViewAdapter As IVsTextView, ByVal textView As ITextView, ByVal nav As ITextStructureNavigator, ByVal broker As ISignatureHelpBroker) Me.m_textView = textView Me.m_broker = broker Me.m_navigator = nav 'add this to the filter chain textViewAdapter.AddCommandFilter(Me, m_nextCommandHandler) End Sub
internal TestSignatureHelpCommandHandler(IVsTextView textViewAdapter, ITextView textView, ITextStructureNavigator nav, ISignatureHelpBroker broker) { this.m_textView = textView; this.m_broker = broker; this.m_navigator = nav; //add this to the filter chain textViewAdapter.AddCommandFilter(this, out m_nextCommandHandler); }
Implementieren Sie die Exec-Methode verwendet, um die Unterzeichnungs-Hilfe eine zu starten, wenn der Befehl einen Filter nach einem Zeichen (empfängt der bekannten Methodennamen und die Sitzung ablehnen, wenn er A) Zeichen empfängt, während die Sitzung noch aktiv ist. In jedem Fall wird der Befehl weitergeleitet.
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 Dim typedChar As Char = Char.MinValue If pguidCmdGroup = VSConstants.VSStd2K AndAlso nCmdID = CUInt(VSConstants.VSStd2KCmdID.TYPECHAR) Then typedChar = CChar(ChrW(CUShort(Marshal.GetObjectForNativeVariant(pvaIn)))) If typedChar.Equals("("c) Then 'move the point back so it's in the preceding word Dim point As SnapshotPoint = m_textView.Caret.Position.BufferPosition - 1 Dim extent As TextExtent = m_navigator.GetExtentOfWord(point) Dim word As String = extent.Span.GetText() If word.Equals("add") Then m_session = m_broker.TriggerSignatureHelp(m_textView) End If ElseIf typedChar.Equals(")"c) AndAlso m_session IsNot Nothing Then m_session.Dismiss() m_session = Nothing End If End If Return m_nextCommandHandler.Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut) End Function
public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) { char typedChar = char.MinValue; if (pguidCmdGroup == VSConstants.VSStd2K && nCmdID == (uint)VSConstants.VSStd2KCmdID.TYPECHAR) { typedChar = (char)(ushort)Marshal.GetObjectForNativeVariant(pvaIn); if (typedChar.Equals('(')) { //move the point back so it's in the preceding word SnapshotPoint point = m_textView.Caret.Position.BufferPosition - 1; TextExtent extent = m_navigator.GetExtentOfWord(point); string word = extent.Span.GetText(); if (word.Equals("add")) m_session = m_broker.TriggerSignatureHelp(m_textView); } else if (typedChar.Equals(')') && m_session != null) { m_session.Dismiss(); m_session = null; } } return m_nextCommandHandler.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut); }
Implementieren Sie die QueryStatus-Methode, sodass sie immer den Befehl weiterleitet.
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); }
Implementieren des Unterzeichnungs-Hilfe-Befehls-Anbieter
Sie können den Befehl Unterzeichnungs-Hilfe dem Implementieren IVsTextViewCreationListener bereitstellen, um den Befehlshandler zu instanziieren, wenn die Textansicht erstellt wird.
Um den Befehl Unterzeichnungs-Hilfe Anbieter implementieren
Fügen Sie eine Klasse hinzu, die TestSignatureHelpController benannt wird, die IVsTextViewCreationListener implementiert und exportieren Sie sie mit NameAttribute, ContentTypeAttributeund TextViewRoleAttribute.
<Export(GetType(IVsTextViewCreationListener)), Name("Signature Help controller"), TextViewRole(PredefinedTextViewRoles.Editable), ContentType("text")> Friend Class TestSignatureHelpCommandProvider Implements IVsTextViewCreationListener
[Export(typeof(IVsTextViewCreationListener))] [Name("Signature Help controller")] [TextViewRole(PredefinedTextViewRoles.Editable)] [ContentType("text")] internal class TestSignatureHelpCommandProvider : IVsTextViewCreationListener
Importieren Sie IVsEditorAdaptersFactoryService (zum Abrufen ITextViewmit dem IVsTextView-Objekt), ITextStructureNavigatorSelectorService (verwendet, um das aktuelle Wort suchen) und ISignatureHelpBroker (die Unterzeichnungs-Hilfe eine starten).
<Import()> Friend AdapterService As IVsEditorAdaptersFactoryService <Import()> Friend Property NavigatorService() As ITextStructureNavigatorSelectorService <Import()> Friend SignatureHelpBroker As ISignatureHelpBroker
[Import] internal IVsEditorAdaptersFactoryService AdapterService; [Import] internal ITextStructureNavigatorSelectorService NavigatorService { get; set; } [Import] internal ISignatureHelpBroker SignatureHelpBroker;
Implementieren Sie die VsTextViewCreated-Methode, indem Sie TestSignatureCommandHandlerinstanziieren.
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 textView.Properties.GetOrCreateSingletonProperty(Function() New TestSignatureHelpCommandHandler(textViewAdapter, textView, NavigatorService.GetTextStructureNavigator(textView.TextBuffer), SignatureHelpBroker)) End Sub
public void VsTextViewCreated(IVsTextView textViewAdapter) { ITextView textView = AdapterService.GetWpfTextView(textViewAdapter); if (textView == null) return; textView.Properties.GetOrCreateSingletonProperty( () => new TestSignatureHelpCommandHandler(textViewAdapter, textView, NavigatorService.GetTextStructureNavigator(textView.TextBuffer), SignatureHelpBroker)); }
Erstellen und Testen von Code
Um diesen Code zu testen, erstellen Sie die SignatureHelpTest-Projektmappe und führen Sie sie in der experimentellen Instanz aus.
So erstellen und testen die SignatureHelpTest-Projektmappe
Erstellen Sie die Projektmappe.
Wenn Sie dieses Projekt im Debugger ausführen, wird eine zweite Instanz von Visual Studio instanziiert.
Erstellen Sie eine Textdatei, und geben Sie Text ein, der das Wort „Hinzufügen“ sowie eine öffnende Klammer umfasst.
Nachdem Sie die öffnende Klammer eingeben, können Sie eine QuickInfo angezeigt, die eine Liste der zwei Signaturen für die add()-Methode anzeigt.
Siehe auch
Aufgaben
Exemplarische Vorgehensweise: Verknüpfen einer Dateinamenerweiterung eines Inhaltstyps