locked
How do i use built-in syntax highligting in an Editor displayed in a WPF dialog window using MEF? RRS feed

  • Question

  • I'm having trouble implementing the existing vb syntax highlighting in an editor that I am putting into a WPF Window.  I am launching this from a VSPackage but I am using MEF to create the editor in the WPF Window.  I've tried some of the examples that use the ITaggerProvider and I am able to get those to work fine on custom syntax but I havn't come close to getting it to highlight vb syntax.  I am probably missing something simple but I'd appeciate any help anyone can provide.

    Here is the code I am using to create the editor.

      Private Sub ShowEditor()
        Dim MyComponentModel As IComponentModel = CType(Microsoft.VisualStudio.Shell.Package.GetGlobalService(GetType(SComponentModel)), IComponentModel)
    
        Dim MyBufferFactory As ITextBufferFactoryService
        MyBufferFactory = MyComponentModel.GetService(Of ITextBufferFactoryService)()
    
        Dim MyContentTypeRegistryService As IContentTypeRegistryService
        MyContentTypeRegistryService = MyComponentModel.GetService(Of IContentTypeRegistryService)()
    
        Dim MyContentType = MyContentTypeRegistryService.GetContentType(MyEditorContentType.ContentTypeName)
    
        Dim textBuffer = MyBufferFactory.CreateTextBuffer("Public Sub TestThis() comment Comment" & vbCrLf & vbCrLf & "End Sub", MyContentType)
    
        Dim MyEditorFactoryService As ITextEditorFactoryService
        MyEditorFactoryService = MyComponentModel.GetService(Of ITextEditorFactoryService)()
    
        Dim view = MyEditorFactoryService.CreateTextView(textBuffer)
    
        Dim editor = MyEditorFactoryService.CreateTextViewHost(view, True)
    
        Dim win As New MyTestWindow(editor)
        win.ShowDialog()
      End Sub
    

    Here is the code to display it in the WPF Window.

      Public Sub New(ByVal testEditor As IWpfTextViewHost)
        InitializeComponent()
    
        Me.bdrEditor.Child = testEditor.HostControl
    
      End Sub
    

    Here is some of the TaggerProvider code I have been trying to implement.

    <Export(GetType(ITaggerProvider)),
    ContentType(MyEditorContentType.ContentTypeName),
    TagType(GetType(ClassificationTag))>
    Friend NotInheritable Class MyEditorTaggerProvider
      Implements ITaggerProvider
    
      <Import()>
      Friend aggregatorFactory As IBufferTagAggregatorFactoryService = Nothing
    
      <Import()>
      Friend ClassificationTypeRegistry As IClassificationTypeRegistryService = Nothing
    
      <Import()>
      Private Property StandardClassifications As IStandardClassificationService
    
    
      Public Function CreateTagger(Of T As ITag)(ByVal buffer As ITextBuffer) As ITagger(Of T) Implements ITaggerProvider.CreateTagger
        Dim TagAggregator As ITagAggregator(Of MyEditorTag) = aggregatorFactory.CreateTagAggregator(Of MyEditorTag)(buffer)
    
        If buffer IsNot Nothing Then
          Return TryCast(New MyEditorTagger(buffer, TagAggregator, ClassificationTypeRegistry), ITagger(Of T))
        Else
          Return Nothing
        End If
      End Function
    End Class
    

     

    Public Class MyEditorTagger
      Implements ITagger(Of ClassificationTag)
    
      Private buffer As ITextBuffer
      Private aggregator As ITagAggregator(Of MyEditorTag)
      Private TagTypes As IDictionary(Of MyEditorTokenTypes, IClassificationType)
    
      Friend Sub New(ByVal buffer As ITextBuffer, ByVal TagAggregator As ITagAggregator(Of MyEditorTag), ByVal typeService As IClassificationTypeRegistryService)
        Me.buffer = buffer
        Me.aggregator = TagAggregator
    
        TagTypes = New Dictionary(Of MyEditorTokenTypes, IClassificationType)
        TagTypes(MyEditorTokenTypes.Comment) = typeService.GetClassificationType(PredefinedClassificationTypeNames.Comment)
        TagTypes(MyEditorTokenTypes.Literal) = typeService.GetClassificationType(PredefinedClassificationTypeNames.Literal)
        TagTypes(MyEditorTokenTypes.Keyword) = typeService.GetClassificationType(PredefinedClassificationTypeNames.Keyword)
    
      End Sub
    
      Public Function GetTags(ByVal spans As NormalizedSnapshotSpanCollection) As System.Collections.Generic.IEnumerable(Of ITagSpan(Of ClassificationTag)) Implements ITagger(Of ClassificationTag).GetTags
    
        Dim tags As New List(Of TagSpan(Of ClassificationTag))
    
        Dim x As Integer = spans.Count
        Dim y As Object = spans.Item(0)
        For Each tagSpan In Me.aggregator.GetTags(spans)
    
          Dim tagSpans = tagSpan.Span.GetSpans(spans(0).Snapshot)
          tags.Add(New TagSpan(Of ClassificationTag)(tagSpans(0), New ClassificationTag(TagTypes(tagSpan.Tag.type))))
        Next tagSpan
    
        Return tags
    
      End Function
    
      Public Event TagsChanged(ByVal sender As Object, ByVal e As Microsoft.VisualStudio.Text.SnapshotSpanEventArgs) Implements Microsoft.VisualStudio.Text.Tagging.ITagger(Of Microsoft.VisualStudio.Text.Tagging.ClassificationTag).TagsChanged
    End Class
    

     

    Public Class MyEditorTag
      Implements ITag
    
      Private privatetype As MyEditorTokenTypes
      Public Property type As MyEditorTokenTypes
        Get
          Return privatetype
        End Get
        Private Set(ByVal value As MyEditorTokenTypes)
          privatetype = value
        End Set
      End Property
    
      Public Sub New(ByVal type As MyEditorTokenTypes)
        Me.type = type
      End Sub
    
    End Class
    Public Enum MyEditorTokenTypes
      Comment
      Literal
      Keyword
    End Enum
    Tuesday, March 1, 2011 10:54 PM

Answers

  • I'm definitely confused as to what the difference between the two is.  I am basically using ITextView and ITextBuffer instead of the IVsTextView and IVsTextBuffer  to create a IWpfTextView to send to my WPF window for display (Code Below).  I may have confused that code with being MEF because most of the MEF examples tend to use ISomeClassName instead of IVsSomeClassName.  I'm not sure which method I used below but the code is more concise and produces the same result.

      Private Sub ShowEditor()
        Dim MyComponentModel As IComponentModel = CType(Microsoft.VisualStudio.Shell.Package.GetGlobalService(GetType(SComponentModel)), IComponentModel)
    
        Dim MyBufferFactory As ITextBufferFactoryService
        MyBufferFactory = MyComponentModel.GetService(Of ITextBufferFactoryService)()
    
        Dim MyContentTypeRegistryService As IContentTypeRegistryService
        MyContentTypeRegistryService = MyComponentModel.GetService(Of IContentTypeRegistryService)()
    
        Dim MyContentType = MyContentTypeRegistryService.GetContentType(MyEditorContentType.ContentTypeName)
    
        Dim textBuffer = MyBufferFactory.CreateTextBuffer("Public Sub TestThis() comment Comment" & vbCrLf & vbCrLf & "End Sub", MyContentType)
    
        Dim MyEditorFactoryService As ITextEditorFactoryService
        MyEditorFactoryService = MyComponentModel.GetService(Of ITextEditorFactoryService)()
    
        Dim view = MyEditorFactoryService.CreateTextView(textBuffer)
    
        Dim editor = MyEditorFactoryService.CreateTextViewHost(view, True)
    
        Dim win As New MyTestWindow(editor)
        win.ShowDialog()
      End Sub
    
    
    • Marked as answer by Victor_Chen Wednesday, March 9, 2011 3:00 AM
    Wednesday, March 2, 2011 10:23 PM

All replies

  • Have you tried setting the LanguageServiceID on the IVsTextBuffer?  Something like (in C#):

    Guid CLSID_VisualBasicLangService = new Guid("{E34ACDC0-BAAE-11D0-88BF-00A0C9110049}");
    int hr = textBuffer.SetLanguageServiceID(ref CLSID_VisualBasicLangService);
    
    

    Ryan

    Tuesday, March 1, 2011 11:20 PM
  • I was trying get this to work just using MEF, but I haven't been able to get it to work using the legacy interfaces either (Latest code below). Is there a predefined ITagAggregator or a set of ITags that I don't know about?

      Private Sub ShowEditor3()
        Dim MyComponentModel As IComponentModel = CType(Microsoft.VisualStudio.Shell.Package.GetGlobalService(GetType(SComponentModel)), IComponentModel)
    
        Dim oleServiceProvider As Microsoft.VisualStudio.OLE.Interop.IServiceProvider
        oleServiceProvider = CType(Microsoft.VisualStudio.Shell.Package.GetGlobalService(GetType(Microsoft.VisualStudio.OLE.Interop.IServiceProvider)), Microsoft.VisualStudio.OLE.Interop.IServiceProvider)
    
        Dim MyBufferFactory As ITextBufferFactoryService
        MyBufferFactory = MyComponentModel.GetService(Of ITextBufferFactoryService)()
    
        Dim MyEditorVSFactoryService As IVsEditorAdaptersFactoryService
        MyEditorVSFactoryService = MyComponentModel.GetService(Of IVsEditorAdaptersFactoryService)()
    
        Dim bufferAdapter As IVsTextBuffer
        bufferAdapter = MyEditorVSFactoryService.CreateVsTextBufferAdapter(oleServiceProvider, MyBufferFactory.TextContentType)
    
        Dim initText As String = "Public Sub TestThis() comment Comment" & vbCrLf & vbCrLf & "End Sub"
        Dim result As Integer = bufferAdapter.InitializeContent(initText, initText.Length)
    
        Dim viewAdapter As IVsTextView
        viewAdapter = MyEditorVSFactoryService.CreateVsTextViewAdapter(oleServiceProvider)
        CType(viewAdapter, IVsWindowPane).SetSite(oleServiceProvider)
    
        Dim _initView() As INITVIEW = {New INITVIEW}
        _initView(0).fSelectionMargin = 100
        _initView(0).fWidgetMargin = 0
        _initView(0).fVirtualSpace = 0
        _initView(0).fDragDropMove = 1
        _initView(0).fVirtualSpace = 0
    
        Dim VBGUID As New Guid("{E34ACDC0-BAAE-11D0-88BF-00A0C9110049}")
        Dim hr As Integer = bufferAdapter.SetLanguageServiceID(VBGUID)
        'Dim txtLines As IVsTextLines = TryCast(bufferAdapter, IVsTextLines)
        'txtLines.SetLanguageServiceID(VBGUID)
    
        viewAdapter.Initialize(TryCast(bufferAdapter, IVsTextLines), IntPtr.Zero, CUInt(TextViewInitFlags.VIF_HSCROLL) Or CUInt(TextViewInitFlags3.VIF_NO_HWND_SUPPORT), _initView)
    
        Dim data As IVsUserData = TryCast(viewAdapter, IVsUserData)
    
        If data IsNot Nothing Then
          Dim guid As Guid = Microsoft.VisualStudio.Editor.DefGuidList.guidIWpfTextViewHost
          Dim obj As Object
          hr = data.GetData(guid, obj)
          If (hr = Microsoft.VisualStudio.VSConstants.S_OK) AndAlso obj IsNot Nothing AndAlso TypeOf obj Is IWpfTextViewHost Then
            Dim editor As IWpfTextViewHost = TryCast(obj, IWpfTextViewHost)
            If editor IsNot Nothing Then
              Dim win As New MyTestWindow(editor)
              win.Show()
            End If
          End If
        End If
    
    
      End Sub
    

     

     

     

     

    Wednesday, March 2, 2011 8:02 PM
  • Well the 'old' interfaces fall into two camps:  strictly legacy (i.e. don't really use anymore, provided via shims) and fairly fundamental even in the new MEF world. For instance IVsTextView and IVsTextBuffer fall into the latter camp as far as I know, so to say something like 'I just want to use MEF' indicates confusion as to how the editor exposes its extensibility and how you interact with it. I don't think you can fully interact with the editor 'just' via MEF, in any realistic scenario.  Well, you can add say adornments to it, but hosting it, hooking it up with language providers, etc... are all a bit more complex than 'adding an adornment'.

    That said, I am not an editor dev, but I have pinged one and pointed him this way to get an answer for you, my guess above was just that, a guess :)

    Ryan

    Wednesday, March 2, 2011 9:20 PM
  • I'm definitely confused as to what the difference between the two is.  I am basically using ITextView and ITextBuffer instead of the IVsTextView and IVsTextBuffer  to create a IWpfTextView to send to my WPF window for display (Code Below).  I may have confused that code with being MEF because most of the MEF examples tend to use ISomeClassName instead of IVsSomeClassName.  I'm not sure which method I used below but the code is more concise and produces the same result.

      Private Sub ShowEditor()
        Dim MyComponentModel As IComponentModel = CType(Microsoft.VisualStudio.Shell.Package.GetGlobalService(GetType(SComponentModel)), IComponentModel)
    
        Dim MyBufferFactory As ITextBufferFactoryService
        MyBufferFactory = MyComponentModel.GetService(Of ITextBufferFactoryService)()
    
        Dim MyContentTypeRegistryService As IContentTypeRegistryService
        MyContentTypeRegistryService = MyComponentModel.GetService(Of IContentTypeRegistryService)()
    
        Dim MyContentType = MyContentTypeRegistryService.GetContentType(MyEditorContentType.ContentTypeName)
    
        Dim textBuffer = MyBufferFactory.CreateTextBuffer("Public Sub TestThis() comment Comment" & vbCrLf & vbCrLf & "End Sub", MyContentType)
    
        Dim MyEditorFactoryService As ITextEditorFactoryService
        MyEditorFactoryService = MyComponentModel.GetService(Of ITextEditorFactoryService)()
    
        Dim view = MyEditorFactoryService.CreateTextView(textBuffer)
    
        Dim editor = MyEditorFactoryService.CreateTextViewHost(view, True)
    
        Dim win As New MyTestWindow(editor)
        win.ShowDialog()
      End Sub
    
    
    • Marked as answer by Victor_Chen Wednesday, March 9, 2011 3:00 AM
    Wednesday, March 2, 2011 10:23 PM
  • Hi ChDawg,

     

    Thanks for sharing and it seems your issue is resolved.

    As far as I know, IVsTextView manages text view from a editor window,

    but ITextView manages text view from any text buffer,

    besides, their members are different.

    If you havev further quesitons, be free to post another thread, and I'll try my best to help.


    Ziwei Chen [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Wednesday, March 9, 2011 3:00 AM
  • Victor,

    I am having a similar problem getting my MEF editor extension to show up in a WPF window. I am using C# instead of VB, but I was able to follow everything chDawg because it is identical to the examples given on Codeplex.

    It appears to me that there really is no answer above. Do you have any advice on what is needed to get my editor extension connected and colorizing?

     


    Quantum Mechanic
    Monday, March 14, 2011 10:55 PM