Click here to Skip to main content
13,833,606 members
Click here to Skip to main content
Add your own
alternative version


55 bookmarked
Posted 11 Jun 2008
Licenced CPOL

WPF: XmlDataProvider Two-Way Data Binding

, 11 Jun 2008
Rate this:
Please Sign up or sign in to vote.
How to perform two-way data binding with the XmlDataProvider within the Windows Presentation Foundation.


This article is targeted for Beginner to Intermediate level WPF programmers. This article assumes that you have some basic knowledge of WPF in regards to layout. If you have no experience with WPF, I strongly suggest reading Sacha Barber’s “WPF: A Beginner’s Guide” series.

The Windows Presentation Foundation (WPF) provides developers with a vast amount of data binding functionality that has been praised by many, including yours truly. However, one area that I’ve found where the data binding falls short is with the XmlDataProvider. Unlike most data binding options in WPF, the XmlDataProvider does not natively support two-way binding. Meaning, if you make modifications to the data via a bound control, the changes are not persisted to the source XML file. This article will explain how to overcome that shortcoming and mimic two-way binding with the XmlDataProvider.


The application in this article was developed with Visual Studio 2008, and targets the 3.5 version of the .NET framework.


The attached demo code consists of a WPF application with a single window and an XML file. Since I enjoy fantasy football, my XML file consists of NFL teams and their associated conferences. An example of the data within the Teams.xml file looks like this:

 <Teams xmlns:xsi="">
    <Name>Arizona Cardinals</Name>
    <Conference>NFC West</Conference>
    <Name>Atlanta Falcons</Name>
    <Conference>NFC South</Conference>

The single window in the application consists of several controls: a ListBox, three Labels, and three TextBoxes. The ListBox displays the NFL team name. The three TextBox controls display the team data associated with the currently selected team within the ListBox.

The WPF window looks like this:


One Way Binding

I won’t get into the details of layout here. However, I want to point out the items within the XAML that make the binding from the source to the control possible. The first, and the most important, item is the XmlDataProvider. The XmlDataProvider specifies the underlying source XML file through its Source attribute. The XPath attribute is used to specify the level at which the data binding occurs. The x:Name attribute exposes the XmlDataProvider to the code-behind.

  <XmlDataProvider x:Name="TeamData" Source="Teams.xml" XPath="Teams/Team" />

You’ll notice in the example above that the XmlDataProvider is contained within Grid.DataContext tags. The layout of the application’s single window is a Grid. Since the XPath statement starts the binding at the team level and the XmlDataProvider is defined within the Grid’s DataContext, the Grid is bound to the data at the team level.

Note: The binding does not have to be done at the Grid level. We could bind the ListItem and other controls to the data within the XmlDataProvider individually. However, there is a synchronization issue when multiple controls bind directly to the XmlDataProvider and use the XPath statement. Explanation of the issue is out of the scope for this article, but can be found at Ian Griffiths’ blog. The approach recommended by Ian was incorporated into this article and the demo code.

The next item in the binding architecture is the ListBox. Since the ListBox is contained within the Grid, and the Grid is bound to the data at the team level, the bindings can be inherited. We can accomplish this simply by setting the ListBox's ItemsSource property to the current bindings.

<ListBox x:Name="TeamsListBox" Margin="0,0,0,20" DockPanel.Dock="Left"


    ItemTemplate="{StaticResource teamItemTemplate}"


    Visibility="Visible" SelectionMode="Single">

Each ListBox item is now bound to a Team element in the XmlDataProvider. To display the team name in the place of the ListBox item, we utilize the teamItemTemplate DataTemplate. The DataTemplate displays a Label control and utilizes the XPath attribute to traverse down to the Name element.

<DataTemplate x:Key="teamItemTemplate">
    <Label Content="{Binding XPath=Name}"/>

The final items in the binding architecture are the TextBox controls to display the selected team’s data. For layout purposes, all of the Label and TextBox controls for the team’s individual items are displayed within a StackPanel. The StackPanel, like the previously mentioned ListBox, is contained within the Grid. We again use the inherited bindings, and by way of the XPath attribute, traverse down to the corresponding element.

<StackPanel Grid.Column="1" Margin="0,0,5,0">           
 <StackPanel Orientation="Horizontal">
   <Label Style="{StaticResource labelStyle}">ID:</Label>
   <TextBox Style="{StaticResource textboxStyle}" Text="{Binding XPath=Id}" />
 <StackPanel Orientation="Horizontal" Style="{StaticResource fieldsetStyle}">
   <Label Style="{StaticResource labelStyle}">Team:</Label>
   <TextBox Style="{StaticResource textboxStyle}" Text="{Binding XPath=Name}" />
 <StackPanel Orientation="Horizontal" Style="{StaticResource fieldsetStyle}">
   <Label Style="{StaticResource labelStyle}">Conference:</Label>
   <TextBox Style="{StaticResource textboxStyle}" Text="{Binding XPath=Conference}" />

This is all that is needed to provide one way binding of WPF controls to an XML file.

Two-Way Binding

Now that we can consume an XML file and bind it to our GUI, it would be really nice if we could persist any changes that we make to the data. Here is where we realize the shortcomings of the XmlDataProvider. If you modify the data within the Team Name textbox, you will see that the changes are persisted within the ListBox. Unfortunately, these changes are only in memory and are not persisted to the underlying XML file. If you stop and restart the application, the original data will be reloaded from the unchanged XML file. Luckily, we can very easily write some code to mimic the binding from the GUI back to the XML source file.

Before I discuss the code, there is one configuration option we must modify. Since the Teams.xml file will need to be deployed with the application’s executable, it is easier to copy it to the output directory upon a successful build. We can right click the Teams.xml file, choose Properties, and select the “Copy if newer” option for the Copy to Output Directory configuration. This will copy the XML file to the same location as the application’s executable. Now, anytime we need to reference the file, we can simply append “Teams.xml” to the path of the currently executing assembly.


There are two code blocks that must be added to the window’s code-behind file to finalize the two-way binding architecture. First, we add code to set the Source property of the XmlDataProvider to the copy of the XML file located in the output directory. This ensures that we are reading from and writing to the same instance of the XML file. Second, we utilize an event handler to execute the code to persist the in-memory data to the XML file. In the demo, I used the Click event handler for the Save button. This could easily be modified to execute within a different event handler such as a TextBox.LostFocus or a Window.Closing event. To persist the changes, we simply call the Save method on the XmlDataProvider’s Document property and specify the XmlDataProvider’s Source as the destination file.

/// <span class="code-SummaryComment"><summary></span>
/// Interaction logic for Window1.xaml
/// <span class="code-SummaryComment"></summary></span>
public partial class Window1 : Window
   public Window1()
       string appPath = System.IO.Path.GetDirectoryName(
       TeamData.Source = new Uri(appPath + @"\Teams.xml");
   private void SaveTeamsButton_Click(object sender, RoutedEventArgs e)
       string source = TeamData.Source.LocalPath;

In Conclusion

Although the XmlDataProvider does have its limitations, they are easily overcome with a few lines of code. Hopefully, this article will benefit those searching for an easy solution.


  • June 9, 2008 – Version 1.0 – Initial release.


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


About the Author

Ryan Bost
Software Developer (Senior)
United States United States
Ryan is a good ol' boy from North Carolina who is obsessed with .NET and general web design.

When he is not coding, he enjoys...

  • spending time with his wife -- knowledge base of locations for all my worldly possessions--honey, where's my...
  • spending time with his twin sons -- my mom says this is payback for my behavior as a child : )
  • playing with his dogs -- they can't hear me calling them to come inside, but they can hear a refrigerator open from a different hemisphere
  • watching college basketball -- Go Tarheels!
  • watching movies from his DVD collection -- over 750 and counting

You may also be interested in...


Comments and Discussions

Questionsuperb Pin
sajijebran1-Jul-15 13:10
membersajijebran1-Jul-15 13:10 
QuestionWhat about a combo box inside a datagrid? Pin
Member 104557569-Jul-14 15:13
memberMember 104557569-Jul-14 15:13 
GeneralBrilliant works ! Pin
Sor Emi2-May-14 0:21
memberSor Emi2-May-14 0:21 
Questionabout the file path Pin
mochou5-Dec-13 21:36
membermochou5-Dec-13 21:36 
QuestionUsing ComboBox instead of ListBox Pin
Member 1015341925-Sep-13 3:41
memberMember 1015341925-Sep-13 3:41 
AnswerRe: Using ComboBox instead of ListBox Pin
Member 1015341925-Sep-13 4:09
memberMember 1015341925-Sep-13 4:09 
GeneralMy vote of 5 Pin
Sriram Bala29-Aug-13 0:29
memberSriram Bala29-Aug-13 0:29 
GeneralMy vote of 5 Pin
Jeanoff18-Jun-13 5:42
memberJeanoff18-Jun-13 5:42 
Questionnavigate items using buttons Pin
miga11129-Nov-11 10:14
membermiga11129-Nov-11 10:14 
GeneralMy vote of 5 Pin
delibey7-Nov-11 11:11
memberdelibey7-Nov-11 11:11 
GeneralBound target only updating when application is restarted/reloaded Pin
Member 779681729-Mar-11 13:34
memberMember 779681729-Mar-11 13:34 
GeneralRe: Bound target only updating when application is restarted/reloaded Pin
Ryan Bost31-Mar-11 16:18
memberRyan Bost31-Mar-11 16:18 
Generalnice one Pin
Sacha Barber11-Jan-11 3:46
mvaSacha Barber11-Jan-11 3:46 
GeneralGreat article! However, data not displaying in listbox when I run sample project Pin
rich123xyz10-Jan-11 13:33
memberrich123xyz10-Jan-11 13:33 
GeneralRe: Great article! However, data not displaying in listbox when I run sample project Pin
Ryan Bost10-Jan-11 16:47
memberRyan Bost10-Jan-11 16:47 
GeneralRe: Great article! However, data not displaying in listbox when I run sample project Pin
rich123xyz11-Jan-11 6:17
memberrich123xyz11-Jan-11 6:17 
GeneralRe: Great article! However, data not displaying in listbox when I run sample project Pin
rich123xyz11-Jan-11 6:24
memberrich123xyz11-Jan-11 6:24 
GeneralRe: Great article! However, data not displaying in listbox when I run sample project Pin
rich123xyz11-Jan-11 6:52
memberrich123xyz11-Jan-11 6:52 
GeneralRe: Great article! However, data not displaying in listbox when I run sample project Pin
Ryan Bost13-Jan-11 3:55
memberRyan Bost13-Jan-11 3:55 
QuestionExcellent!! Pin
AlainMesias9-Nov-10 1:33
memberAlainMesias9-Nov-10 1:33 
AnswerRe: Excellent!! Pin
Ryan Bost10-Jan-11 19:25
memberRyan Bost10-Jan-11 19:25 
GeneralMy vote of 5 Pin
AlainMesias9-Nov-10 1:28
memberAlainMesias9-Nov-10 1:28 
GeneralGreat solution.. Here's is another way.. [modified] Pin
Jostein Kjellsen23-Feb-10 0:15
memberJostein Kjellsen23-Feb-10 0:15 
GeneralThank You Very Much Pin
mselvaraj15-Dec-09 21:08
membermselvaraj15-Dec-09 21:08 
GeneralLittle Issue Pin
HarvP16-Jun-09 7:59
memberHarvP16-Jun-09 7:59 
This is a great article however I have found then when data in the textbox is changed in code as opposed to someone typing the changes are not saved. I can't seem to narrow down why this happens but I will keep at it.

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.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web06 | 2.8.190114.1 | Last Updated 11 Jun 2008
Article Copyright 2008 by Ryan Bost
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid