Click here to Skip to main content
15,867,686 members
Articles / Desktop Programming / WPF

A Simple WPF XML Document Viewer Control

Rate me:
Please Sign up or sign in to vote.
4.96/5 (34 votes)
7 Apr 2010CPOL3 min read 226K   9.5K   64   40
This article introduces a simple XML document viewer control for WPF applications to display XML documents in a nicely formatted way.

Introduction

This article introduces a simple XML document viewer control for WPF applications to display XML documents in a nicely formatted way.

Background

In one of my recent WPF projects, I needed to display some XML documents in a formatted way similar to how Internet Explorer displays them. My first option was to use the WPF "WebBrowser" control. When I navigate the "WebBrowser" control to an XML file on the hard drive or some XML content on the web, it is displayed fine. But when I try to navigate the "WebBrowser" control to an in-memory XML string, the control fails to recognize that the content is XML and the display format is completely wrong. I will then need some other alternatives.

I need an XML document viewer control that displays the XML content in a formatted way, and I will need the control to take the XML content from a "System.Xml.XmlDocument" object, so I can dynamically generate the XML content and display it.

The XML document viewer control introduced in this article is inspired by Marco Zhou's blog. What I did is simply make the idea into an easier to use user control, and provide a demo application to show how the control is used.

The demo Visual Studio Solution that comes with this article has two .NET projects. One is the user control class library and the other is a simple WPF application to demonstrate how the control is used. The Visual Studio Solution is developed in Visual Studio 2008.

Overview of the Simple Visual Studio Solution

The Visual Studio Solution "XMLViewerDomo" has two .NET projects.

VSSolution.JPG

The "XMLViewer" project is a class library to create the XML document viewer control, and the "DemoApplication" project is a WPF application to demonstrate how the control is used.

The XML Document Viewer Control

The XML document viewer control is implemented in "Viewer.xaml":

XML
<UserControl x:Class="XMLViewer.Viewer"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:xmlstack="clr-namespace:System.Xml;assembly=System.Xml"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
 
    <UserControl.Resources>
        <SolidColorBrush Color="Blue" x:Key="xmlValueBrush"/>
        <SolidColorBrush Color="Red" x:Key="xmAttributeBrush"/>
        <SolidColorBrush Color="DarkMagenta" x:Key="xmlTagBrush"/>
        <SolidColorBrush Color="Blue" x:Key="xmlMarkBrush"/>
 
        <DataTemplate x:Key="attributeTemplate">
            <StackPanel Orientation="Horizontal" 
                        Margin="3,0,0,0" HorizontalAlignment="Center">
                <TextBlock Text="{Binding Path=Name}" 
                           Foreground="{StaticResource xmAttributeBrush}"/>
                <TextBlock Text="=&quot;" 
                           Foreground="{StaticResource xmlMarkBrush}"/>
                <TextBlock Text="{Binding Path=Value}" 
                           Foreground="{StaticResource xmlValueBrush}"/>
                <TextBlock Text="&quot;" 
                           Foreground="{StaticResource xmlMarkBrush}"/>
            </StackPanel>
        </DataTemplate>
 
        <Style TargetType="{x:Type TreeViewItem}">
            <Setter Property="IsExpanded" Value="True"/>
        </Style>
 
        <HierarchicalDataTemplate x:Key="treeViewTemplate" 
                                  ItemsSource="{Binding XPath=child::node()}">
            <StackPanel Orientation="Horizontal" Margin="3,0,0,0" 
                        HorizontalAlignment="Center">
                <TextBlock Text="&lt;" HorizontalAlignment="Center" 
                           Foreground="{StaticResource xmlMarkBrush}" 
                           x:Name="startTag"/>
 
                <TextBlock Text="{Binding Path=Name}"
                    Margin="0"
                    HorizontalAlignment="Center"
                    x:Name="xmlTag"
                    Foreground="{StaticResource xmlTagBrush}"/>
 
                <ItemsControl
                    ItemTemplate="{StaticResource attributeTemplate}"
                    ItemsSource="{Binding Path=Attributes}"
                    HorizontalAlignment="Center">
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <StackPanel Orientation="Horizontal"/>
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                </ItemsControl>
 
                <TextBlock Text="&gt;" HorizontalAlignment="Center" 
                           Foreground="{StaticResource xmlMarkBrush}" 
                           x:Name="endTag"/>
            </StackPanel>
 
            <HierarchicalDataTemplate.Triggers>
                <DataTrigger Binding="{Binding NodeType}">
                    <DataTrigger.Value>
                        <xmlstack:XmlNodeType>Text</xmlstack:XmlNodeType>
                    </DataTrigger.Value>
                    <Setter Property="Text" Value="{Binding InnerText}" 
                            TargetName="xmlTag"/>
                    <Setter Property="Foreground" Value="Blue" 
                            TargetName="xmlTag"/>
                    <Setter Property="Visibility" Value="Collapsed" 
                            TargetName="startTag"/>
                    <Setter Property="Visibility" Value="Collapsed" 
                            TargetName="endTag"/>
                </DataTrigger>
 
                <DataTrigger Binding="{Binding HasChildNodes}" Value="False">
                    <Setter Property="Text" Value="/&gt;" TargetName="endTag"/>
                </DataTrigger>
            </HierarchicalDataTemplate.Triggers>
        </HierarchicalDataTemplate>
    </UserControl.Resources>
 
    <Grid>
        <TreeView Grid.Row="2" Grid.ColumnSpan="2" Name="xmlTree" 
                  ItemTemplate="{StaticResource treeViewTemplate}"/>
    </Grid>
</UserControl>

The code-behind file for "Viewer.xaml" is the following:

C#
using System.Windows.Controls;
using System.Windows.Data;
using System.Xml;
 
namespace XMLViewer
{
    /// <summary>
    /// Interaction logic for Viewer.xaml
    /// </summary>
    public partial class Viewer : UserControl
    {
        private XmlDocument _xmldocument;
        public Viewer()
        {
            InitializeComponent();
        }
 
        public XmlDocument xmlDocument
        {
            get { return _xmldocument; }
            set
            {
                _xmldocument = value;
                BindXMLDocument();
            }
        }
 
        private void BindXMLDocument()
        {
            if (_xmldocument == null)
            {
                xmlTree.ItemsSource = null;
                return;
            }
 
            XmlDataProvider provider = new XmlDataProvider();
            provider.Document = _xmldocument;
            Binding binding = new Binding();
            binding.Source = provider;
            binding.XPath = "child::node()";
            xmlTree.SetBinding(TreeView.ItemsSourceProperty, binding);
        }
    }
}

The Demo WPF Application "DemoApplication"

The main application window for the demo WPF application is implemented in the "XMLViewerDemoApplication.xaml":

XML
<Window x:Class="DemoApplication.XMLViewerDemoApplication"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:XMLViewer="clr-namespace:XMLViewer;assembly=XMLViewer"
    FontFamily="Verdana" Icon="Images\icon_music.ico"
    Title="XMLViewer User Control Demonstration Application">
    
    <Grid Margin="10, 10, 10, 10">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="5"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        
        <Grid Grid.Row="0">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="100" />
                <ColumnDefinition Width="100" />
                <ColumnDefinition Width="5" />
            </Grid.ColumnDefinitions>
 
            <TextBox Name="txtFilePath" IsReadOnly="True"
                     Grid.Column="0" HorizontalAlignment="Stretch" />
            <Button Margin="3, 0, 0, 0" Content="Browse..." 
                    Click="BrowseXmlFile" Grid.Column="1"/>
            <Button Margin="3, 0, 0, 0" Content="Clear" 
                    Click="ClearXmlFile" Grid.Column="2"/>
        </Grid>
        
        <XMLViewer:Viewer x:Name="vXMLViwer" Grid.Row="2" />
    </Grid>
</Window>

The code-behind file for "XMLViewerDemoApplication.xaml" is the following:

C#
using System.Windows;
using System.Xml;
 
namespace DemoApplication
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class XMLViewerDemoApplication : Window
    {
        public XMLViewerDemoApplication()
        {
            InitializeComponent();
        }
 
        private void BrowseXmlFile(object sender, RoutedEventArgs e)
        {
            Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
            dlg.CheckFileExists = true;
            dlg.Filter = "XML Files (*.xml)|*.xml|All Files(*.*)|*.*";
            dlg.Multiselect = false;
 
            if (dlg.ShowDialog() != true) { return; }
 
            XmlDocument XMLdoc = new XmlDocument();
            try
            {
                XMLdoc.Load(dlg.FileName);
            }
            catch (XmlException)
            {
                MessageBox.Show("The XML file is invalid");
                return;
            }
 
            txtFilePath.Text = dlg.FileName;
            vXMLViwer.xmlDocument = XMLdoc;
        }
 
        private void ClearXmlFile(object sender, RoutedEventArgs e)
        {
            txtFilePath.Text = string.Empty;
            vXMLViwer.xmlDocument = null;
        }
    }
}

To demonstrate how the user control is used, what this WPF application does is to first let the user browse an XML file and load the XML file into a "System.Xml.XmlDocument" object. After the "XMLDodument" object is loaded, it is assigned to the "xmlDocument" property of the user control. If we want to clear the XML display from the user control, we can simply assign "null" to the "xmlDocument" property.

Run the Demo Application

Set the "DemoApplication" project as the "Startup" project, you can debug launch the demo application. Browse an XML file, the application will display the XML file in a nice format.

RunApplication.JPG

The above picture shows how the control displays a "Web.config" file for a web application. I included this "Web.config" file in the zip file coming with this article, but you can test with any valid XML files that you have in this application. Each node in the XML document can be expanded and collapsed independently and the content of the XML is properly colored.

Points of Interest

This article introduced a formatted XML document viewer WPF control. The control takes a "System.Xml.XmlDocument" object as the XML content. It is simple, flexible and easy to use.

History

This is the first revision of the article.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
I have been working in the IT industry for some time. It is still exciting and I am still learning. I am a happy and honest person, and I want to be your friend.

Comments and Discussions

 
QuestionMessage Closed Pin
14-May-22 2:49
Member 1563588214-May-22 2:49 
QuestionHow to display closing tag name also rather than showing /> Pin
Member 103156417-Jun-17 6:26
Member 103156417-Jun-17 6:26 
QuestionJust great and simple ! Pin
EdwinEP20-Apr-16 19:34
EdwinEP20-Apr-16 19:34 
Bugnot showed the closeing tag Pin
kumarpr5-Oct-15 17:46
kumarpr5-Oct-15 17:46 
Questioneach node is different background color Pin
kumarpr1-Oct-15 23:55
kumarpr1-Oct-15 23:55 
Bugnot able to visualize more than 250 lines Pin
kumarpr29-Sep-15 18:38
kumarpr29-Sep-15 18:38 
Thanks for sharing. not able to visualize more than 250 lines.please help me to suggest, how to show more than 250 and above lines.

GeneralRe: not able to visualize more than 250 lines Pin
Dr. Song Li30-Sep-15 3:29
Dr. Song Li30-Sep-15 3:29 
GeneralRe: not able to visualize more than 250 lines Pin
Dr. Song Li30-Sep-15 3:32
Dr. Song Li30-Sep-15 3:32 
GeneralRe: not able to visualize more than 250 lines Pin
kumarpr4-Oct-15 22:49
kumarpr4-Oct-15 22:49 
Questionhow to show more than 250 and above lines Pin
kumarpr28-Sep-15 20:40
kumarpr28-Sep-15 20:40 
Questiontemplate and closing didn't work. Pin
keremburak30-Apr-13 3:42
professionalkeremburak30-Apr-13 3:42 
QuestionChanges for data binding Pin
Marco Mastropaolo18-Feb-13 1:08
Marco Mastropaolo18-Feb-13 1:08 
AnswerRe: Changes for data binding Pin
Dr. Song Li18-Feb-13 3:50
Dr. Song Li18-Feb-13 3:50 
QuestionRE;Visual studio2012 Pin
nitishsingh3189@gmail.com22-Sep-12 4:06
nitishsingh3189@gmail.com22-Sep-12 4:06 
AnswerRe: RE;Visual studio2012 Pin
Dr. Song Li22-Sep-12 4:47
Dr. Song Li22-Sep-12 4:47 
QuestionNice Work Searching exactly for this Pin
Mayur225813-Jun-12 20:03
Mayur225813-Jun-12 20:03 
QuestionTags not closed Pin
Jawahar Suresh Babu23-May-12 0:07
Jawahar Suresh Babu23-May-12 0:07 
GeneralMy vote of 5 Pin
dexterama10-May-12 3:01
professionaldexterama10-May-12 3:01 
GeneralMy vote of 5 Pin
Dave Matsumoto29-Mar-12 9:25
Dave Matsumoto29-Mar-12 9:25 
QuestionVery Great Work Pin
Sharp_forever25-Mar-12 9:27
Sharp_forever25-Mar-12 9:27 
QuestionGood job man! Pin
dimas197130-Jan-12 4:15
dimas197130-Jan-12 4:15 
Questionexpand all nodes everytime a xmldocument is loaded Pin
brndnbgable26-Jan-12 2:46
brndnbgable26-Jan-12 2:46 
AnswerRe: expand all nodes everytime a xmldocument is loaded Pin
Dr. Song Li26-Jan-12 14:20
Dr. Song Li26-Jan-12 14:20 
QuestionEvent Handling Pin
Miros799-Jan-12 12:30
Miros799-Jan-12 12:30 
GeneralMy vote of 5 Pin
Hamid Noorbakhsh8-Dec-11 11:21
professionalHamid Noorbakhsh8-Dec-11 11:21 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.