CODEDIGEST
Home » Articles
Search
 

Technologies
 

Sponsored links
 

CodeDigest Navigation
 

Technology News
No News Feeds available at this time.
 

Community News
No News Feeds available at this time.
 
How to perform WPF Data Binding using LINQ to XML

By Balamurali Balaji
Posted On Apr 02,2009
Article Rating:
Be first to rate
this article.
No of Comments: 0
Category: WPF
Print this article.

How to perform WPF Data Binding using LINQ to XML

 

Most of the times, you may have to display XML data in your WPF applications. Traditionally, you might use XML plug-ins offered by ADO.NET. But, LINQ is the mantra now. Using LINQ to XML, it is much easier and fun to bind your WPF controls and perform data binding as a new fashion.

 

System.Xml.Linq

 

Before binding XML data with WPF controls, let me give an overview about System.Xml.Linq namespace. It contains the classes for LINQ to XML. LINQ to XML is an in-memory XML programming interface that enables you to modify XML documents efficiently and easily.

 

Using LINQ to XML, you can:

 

1.      Load XML from files or streams.

2.      Serialize XML to files or streams.

3.      Create XML trees from scratch using functional construction.

4.      Query XML trees using LINQ queries.

5.      Manipulate in-memory XML trees.

6.      Validate XML trees using XSD.

7.      Use a combination of these features to transform XML trees from one shape into another.

 

For Data Binding efforts, we need to focus on two classes in this namespace, namely: XAttribute and XElement. The dynamic properties of these classes help us to exactly bind the control to the respective elements in XML data.

 

The XAttribute class is derived from XObject class and it represents an XML attribute.  Attributes are not derived from XNode; they are not nodes in the XML tree. Instead, they are simply name/value pairs associated with an element

 

The XElement class is derived from XContainer class which derives from XNode class and it represents an XML element, the fundamental XML construct. An element has an XName, optionally one or more attributes, and can optionally contain contents like XElement, XComment, XText and XProcessingInstruction.

 

Each XElement contains a list of the attributes for that element. Attributes must have a qualified name that is unique to the element.

 

As an example, the following C# code shows the common task of creating an element that contains an attribute:

 

XElement phone = new XElement("Phone",    new XAttribute("Type", "Home"),     "555-555-5555");

Console.WriteLine(phone);

 

Dynamic Data Binding in WPF and Dynamic Properties

 

Having learnt that we have couple of XLinq classes available with us, the next step is to understand how data binding can be performed with these classes.

 

By default, data binding occurs only when the target UI element is initialized. This is called one-time binding. For most purposes, this is insufficient; with two-way binding, changes to the source are automatically propagated to the target, and changes to the target are automatically propagated to the source.

 

For one-way or two-way binding to occur, the source must implement a change notification mechanism, for example by implementing the INotifyPropertyChanged interface or by using a PropertyNameChanged pattern for each property supported.

Most LINQ to XML classes do not qualify as proper WPF dynamic data sources. To support WPF data binding, LINQ to XML exposes a set of dynamic properties. These dynamic properties are special run-time properties in the XAttribute and XElement classes to act as dynamic data sources for WPF and implement change notifications.

 

The dynamic properties in the XAttribute and XElement classes cannot be accessed like standard properties. In C#, dynamic properties can only be accessed at run time through facilities provided by the System.ComponentModel namespace.  However, in an XML source dynamic properties can be accessed through a straightforward notation in the following form:

 

<object>.<dynamic-property>

 

The dynamic properties for these two classes either resolve to a value that can be used directly, or to an indexer such as Elements and Descendants property of XElement, that must be supplied with an index to obtain the resulting value or collection of values.

 

To implement WPF dynamic binding, dynamic properties will be used with facilities provided by the System.Windows.Data namespace, most notably the Binding class.

 

XML as Resource Data in XAML

 

Now, let us look at various elements of XAML that can be used to define and use XML data. Also, this section explains the elements required for defining the resources, templates and subsequent binding of these to the WPF controls.

 

Inside the Windows.Resources tag, we can declare the data source to XML data using the <ObjectDataProvider> and also a <DataTemplate> that follows a certain pattern of data elements.

 

The <ObjectDataProvider> tag, declares an instance of ObjectDataProvider class, named “LoadedBooks” that uses a XElement as the source. This XElement is initialized by parsing an embedded XML document (a CDATA element). Also, white space is preserved when declaring the embedded XML document and when it is parsed. The reason is that the TextBlock control, which is used to display the raw XML, has no special XML formatting capabilities.

 

A DataTemplate named “BookTemplate” is defined to display the entries in the respective controls in the Book List UI section. It uses data binding and LINQ to XML dynamic properties to retrieve the book ID and book name through the following assignments:




Text="{Binding Path=Attribute[id].Value}"

Text="{Binding Path=Value}"

 

<Window.Resources> tag with both of these definitions is given below:

 

<Window.Resources>

        <!-- Books provider and inline XML data -->

<ObjectDataProvider x:Key="LoadedBooks" ObjectType="{x:Type xlinq:XElement}"                  MethodName="Parse">

              <ObjectDataProvider.MethodParameters>

                     <system:String xml:space="preserve">

<![CDATA[

<books xmlns="http://www.mybooks.com">

<book id="1">Seven ways to Success</book>

<book id="2">My Experiments with Truth</book>

<book id="3">Leadership Skills</book>

<book id="4">India and Politics Today</book>

</books>

]]>               

                     </system:String>

                     <xlinq:LoadOptions>PreserveWhitespace</xlinq:LoadOptions>

            </ObjectDataProvider.MethodParameters>

        </ObjectDataProvider>

 

        <!-- Template for use in Books List listbox. -->

        <DataTemplate x:Key="BookTemplate">

            <StackPanel Orientation="Horizontal">

                <TextBlock Margin="3" Text="{Binding Path=Attribute[id].Value}"/>

                <TextBlock Margin="3" Text="-"/>

                <TextBlock Margin="3" Text="{Binding Path=Value}"/>

            </StackPanel>

        </DataTemplate>

    </Window.Resources>

 

Once the DataTemplate is ready as a data resource, Data Binding can be performed with the WPF controls in the User Interface.

 

 In the <StackPanel> tag, the DataContext property is set to the “LoadedBooks” data provider.

 

DataContext="{Binding Source={StaticResource LoadedBooks}}

 

This makes it possible for the TextBlock named tbRawXml to display the raw XML by binding to this data provider's Xml property:

 

Text="{Binding Path=Xml}"

 

The ListBox in the Book List UI section, sets the template for its display items to the “BookTemplate“ resource and the actual values of the books are bound to the items in the list box.

 

<ListBox Name="lbBooks" Height="200" Width="415" ItemTemplate ="{StaticResource BookTemplate}">

                <ListBox.ItemsSource>

                    <Binding Path="Elements[{http://www.mybooks.com}book]"/>

                </ListBox.ItemsSource>

 </ListBox>

 

Upon selecting a book in the list box, we need to display the corresponding details in textboxes for viewing and editing purposes. This requires a binding to the parent data source in the listbox and a two way data binding so that the current values of the book elements are displayed to and updated from the two text boxes in this panel. Data binding to dynamic properties is similar to that used in the BookTemplate data template:

 

   <StackPanel Margin="1" DataContext="{Binding ElementName=lbBooks, Path=SelectedItem}">

....

....

        <TextBox Name="editAttributeTextBox" Width="410" Text="{Binding Path=Attribute[id].Value}">

...

...

          <TextBox Name="editValueTextBox" Width="410" Text="{Binding Path=Value}" Height="25">

         

 

Walkthrough:  Creating a WPF application that shows LINQ to XML Data Binding with inline XML data

 

Now, let us create a complete application that would make use of above discussed features. This sample program enables the user to view and manipulate a list of books that is stored as an embedded XML element.

 

Start Visual Studio and create a C# WPF application named WPFDataBindingLinqToXml. The project must use the .NET Framework 3.5 (or later).

 

Design the UI as shown in the screenshot below as XAML markup in the Window1.Xaml.

 

 

Also, modify the code in Window1.Xaml.cs file as below:

 

        XNamespace mybooks = "http://www.mybooks.com";

        XElement bookList;

 

        public Window1()

        {

            InitializeComponent();

            bookList = (XElement)((ObjectDataProvider)Resources["LoadedBooks"]).Data;

        }

        void OnRemoveBook(object sender, EventArgs e)

        {

            int index = lbBooks.SelectedIndex;

            if (index < 0) return;

 

            XElement selBook = (XElement)lbBooks.SelectedItem;

            //Get next node before removing element.

            XNode nextNode = selBook.NextNode;

            selBook.Remove();

 

            //Remove any matching newline node.

            if (nextNode != null && nextNode.ToString().Trim().Equals(""))

            { nextNode.Remove(); }

 

            //Set selected item.

            if (lbBooks.Items.Count > 0)

            { lbBooks.SelectedItem = lbBooks.Items[index > 0 ? index - 1 : 0]; }

        }

 

        void OnAddBook(object sender, EventArgs e)

        {

            if (String.IsNullOrEmpty(tbAddID.Text) || String.IsNullOrEmpty(tbAddValue.Text))

            {

                MessageBox.Show("Please supply both a Book ID and a Value!", "Entry Error!");

                return;

            }

            XElement newBook = new XElement(mybooks + "book",  new XAttribute("id", tbAddID.Text),

                                tbAddValue.Text);

            bookList.Add("  ", newBook, "\r\n");

        }

Basically, the above code uses the XElement, XNode and XNamespace objects to manipulate Xml data along with binding controls.

 

Lastly, build the solution by pressing Ctrl+Shift+B, and then run it by pressing F5. The project should compile without errors and run as a generic WPF application.

 

Using the WPFDataBindingLinqToXml sample application and its User Interface

 

The top section of the UI displays the raw XML that represents the book list. It is displayed using a WPF TextBlock control, which does not enable interaction through the mouse or keyboard.

 

The second vertical section, labeled Book List, displays the books as a plain text ordered list. It uses a ListBox control that enables selection though the mouse or keyboard.

 

The following tasks may be performed in this UI:

 

Ø       To delete an existing book from the list, select it in the Book List section, then click the Remove Selected Book button. Notice that the book entry has been removed from both the book and the raw XML source listings.

 

Ø       To add a new book to the list, enter values into the ID and ValueTextBox controls in the last section, Add New Book, and then click the Add Book button. Note that the book is appended to the list in both the book and XML listings. This program does not validate input values.

 

Ø       Select the book entry in the second Book List section. Its current values should be displayed in the third section.

 

Ø       To Edit Selected Book, Edit the values using the keyboard. As soon as either TextBox control looses focus, changes are automatically propagated to the XML source and book listings.

 

Conclusion

 

This article has explained the theory and steps involved in developing a WPF application that can bind to XML data stored inline using LINQ to XML classes. The same can also be done with XML data stored in a file system. The next part of this article would explain how to bind to an external XML data with slighter modifications in this sample. Hope you enjoyed and found useful in this article.

 

Similar Articles
You can contribute to CodeDiget.Com:
Donate to CodeDigest.com
Article Feedback
Comments