Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Enhancing The Web Browser Control For XML

0.00/5 (No votes)
9 Apr 2010 1  
Shows how to enhance the MS web browser control for use with XML in VB.net

Download EnhancedBrowserControl.zip - 26.34 KB

Introduction

I've read and heard comments lamenting the fact that the MS .net Web Browser control (System.Windows.Forms.WebBrowser) doesn't behave like Internet Explorer, or lacks some of the feature support that IE has. Chief among these complaints is the one that it doesn't support the displaying of XML the way IE does, all pretty and ready for printing. You could take the view, as do I, that this is the way it should be. The Web Browser control is a basic (although powerful) managed wrapper for the Web Browser ActiveX control (in Shdocvw.dll). IE uses Shdocvw.dll too, but when you use a .net Web Browser control in your application, you're not using a component of IE, you're using a component that IE uses. IE extends it's functionality, and if the need arises... so must you.

So Very Useful

Since the basic WB control can be so useful in many different applications that you develop, I recommend you consider creating a wrapper of your own which you reuse in each project where you need a WB control. As you progress from project to project, you'll add more features as needed by each project. Each time you do this, you potentially save yourself a lot of time with each new project you use it in. You can either put it into its own class library project, as I have in this article. Alternatively you could maintain one code file which you keep importing into other projects. The latter approach requires you to be using a version control or file repository system (such as SourceSafe) so that you can have the same physical file in many projects. Besides that, you may have other class files that you want to add later. So I would suggest building your own library to contain it.

No Need - There's One Right Here

So that's the approach I've taken with the project files associated with this article. I've created a Class Library that contains one class which, using my extensive imagination and creative flare I have named... 'WebBrowser'. This is of course a wrapper for... you guessed... the WebBrowser. For those new to the subject of inheritance, the distinction between the two rests in the fact that EnhancedControls.WebBrowser (my namespace) inherits from, and extends System.Windows.Forms.WebBrowser (an MS namespace). So the issue my WB control will tackle is the one I mentioned at the start - support for displaying XML. But you can add other features to it that are appropriate for your needs too.

Transforming XML

Some people are prone to turning this subject into rocket science. My view is that if a transformation works with the XML files you're working with... it works. Compile the code, make the coffee, and move on. You can always add support for other transformations later on when you encounter some XML with which it doesn't work, if that ever happens. So when I went out looking for a good transformation I found one provided by Steve Muench. I embedded that xslt file into the resources of my library project because I don't want my library to have any dependencies on files external to itself.

Once you have an appropriate transformation at hand, actually making the transform happen is very easy. Here is the code for that:

    
Public Sub DisplayPrettyXML(ByVal oReader As XmlReader)
    Try 'to display the XML contained in the Reader
        'If I don't currently have a Transformation object then...
        If IsNothing(moXsltTransformation) Then
            'Create one. This object will be reused on each call to any
            'of the DisplayPrettyXML overloads.
            moXsltTransformation = New XslCompiledTransform(False)
            'Create a TextReader and load it with the xslt file from my resources
            Using oTextReader As TextReader = New StringReader(My.Resources.PrettyPrint)
                'Create an XmlReader from the TextReader
                Using oXsltReader As XmlReader = XmlReader.Create(oTextReader)
                    'Load the style sheet into the Transformation object
                    moXsltTransformation.Load(oXsltReader)
                End Using
            End Using
        End If
        'If I don't currently have a stringbuilder object then...
        If IsNothing(moStringBuilder) Then
            'Make one. This object will be reused on each call to any
            'of the DisplayPrettyXML overloads.
            moStringBuilder = New StringBuilder
        Else 'Otherwise, reuse the one I have. Empty it.
            moStringBuilder.Remove(0, moStringBuilder.Length)
        End If
        'Create an XmlWriter that will fill the stringbuilder with xml
        Using oXmlWriter As XmlWriter = XmlWriter.Create(moStringBuilder)
            'Do the transformation
            moXsltTransformation.Transform(oReader, Nothing, oXmlWriter)
        End Using
        'I'm decended from the MS WebBrowser control, so I can just
        'set my DocumentText property to the now populated stringbuilder
        Me.DocumentText = moStringBuilder.ToString
    Catch ex As Exception
        Me.DocumentText = ERR_HTML
    End Try
End Sub

One of my big problems is that I don't always practice what I preach. Only two paragraphs and one sub-routine ago did I say (in not so many words), don't bother to cross bridges you haven't come to yet. Some bridges I immediately spotted in the foggy distance convinced me that I may not always have an XmlReader object to pass to the DisplayPrettyXML() routine. Sometimes I'll have a file, other times perhaps and XMLDocument object. So I immediately crossed all the bridges not yet reached, and wrote four overloads for DisplayPrettyXML(). I'll list just one of them here:

Public Sub DisplayPrettyXML(ByVal strFilePath As String)
    Try 'to convert the file found at the location into an XmlReader
        'and pass it to the overload of DisplayPrettyXML
        DisplayPrettyXML(XmlReader.Create(File.OpenRead(strFilePath)))
    Catch ex As Exception
        Throw
    End Try
End Sub

The other overloads accept: A Stream, an XMLDocument instance, and an XMLDataDocument instance, and they're all pretty small like the one above.

 webbrowser.png

Using the code

To test my new WB component I created a Windows Forms Application, with one form, dropped my WB control onto that form and added five buttons. Each button causes the WB control to do the same thing, but with five different (although they share the same structure) XML files.

Private Sub cmdFile_Click(ByVal sender As System.Object, _
                          ByVal e As System.EventArgs) _
                          Handles cmdFile.Click
    'Ask the WebBrowser to display XML from a file
    WebBrowser.DisplayPrettyXML("XMLFiles\MusicLibrarySting.xml")
End Sub

Private Sub cmdStream_Click(ByVal sender As System.Object, _
                            ByVal e As System.EventArgs) _
                            Handles cmdStream.Click
    'Ask the WebBrowser to display XML from a stream
    Using oStream As FileStream = File.OpenRead( _
                        "XMLFiles\MusicLibraryMadonna.xml")
        WebBrowser.DisplayPrettyXML(oStream)
    End Using
End Sub

Private Sub cmdXMLReader_Click(ByVal sender As System.Object, _
                               ByVal e As System.EventArgs) _
                               Handles cmdXMLReader.Click
    'Ask the WebBrowser to display XML from an XmlReader
    Using oXmlReader As XmlReader = XmlReader.Create( _
                        "XMLFiles\MusicLibraryREM.xml")
        WebBrowser.DisplayPrettyXML(oXmlReader)
    End Using
End Sub

Private Sub cmdXMLDoc_Click(ByVal sender As System.Object, _
                            ByVal e As System.EventArgs) _
                            Handles cmdXMLDoc.Click
    'Ask the WebBrowser to display XML from an 
    'XmlDocument instance
    Dim oXmlDocument As XmlDocument = New XmlDocument()
    oXmlDocument.Load("XMLFiles\MusicLibrarySeanPaul.xml")
    WebBrowser.DisplayPrettyXML(oXmlDocument)
End Sub

Private Sub cmdXMLDataDoc_Click(ByVal sender As System.Object, _
                                ByVal e As System.EventArgs) _
                                Handles cmdXMLDataDoc.Click
    'Ask the WebBrowser to display XML from an 
    'XmlDataDocument instance
    Dim oXmlDataDocument As XmlDataDocument = New XmlDataDocument()
    oXmlDataDocument.Load("XMLFiles\MusicLibraryBeatles.xml")
    WebBrowser.DisplayPrettyXML(oXmlDataDocument)
End Sub

Points of Interest

  • The System.Windows.Forms.WebBrowser control is a good example of a situation where you know of a component that comes close to what you need, but just stops a little short. This can apply to any control and many other .net classes too.
  • If you can set aside some time within your project, it's always a good idea to consider spending it on making library-based functionality that you know you're going to use again. The .net framework lends itself, and supports you in this approach because there are so many aspects of it that you can customise and build upon.

History

None.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here