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

WPF: XmlDataProvider Two-Way Data Binding - Enhanced

0.00/5 (No votes)
11 Jan 2011 1  
How to perform two-way data binding with the XmlDataProvider within the Windows Presentation Foundation including all CRUD operations.

Introduction

In my previous article, WPF: XmlDataProvider Two-Way Data Binding, I discussed how the XmlDataProvider does not natively support two-way binding and provided a simple workaround to address the issue. The binding in the previous article only demonstrated read and update operations. In response to several reader comments inquiring about insert and delete operations, I have updated the demo code and provided this brief article.

Background

The application in my previous article was developed with Visual Studio 2008 and targeted the 3.5 version of the .NET framework. The downloadable project above for this article was upgraded to Visual Studio 2010.

Using the Code

You will notice from the screenshot below that I have added two new buttons to the form for the purpose of inserting and deleting records. Each button has a corresponding event handler to persist the changes to the source XML file.

Screenshot.gif

We'll start with the New button and its event handler. The button simply removes the listbox selection and clears the Team form to prepare for a new record.

private void NewTeamButton_Click(object sender, RoutedEventArgs e)
{
     TeamsListBox.SelectedIndex = -1;
     TeamIDTextBox.Text = String.Empty;
     TeamNameTextBox.Text = String.Empty;
     ConferenceTextBox.Text = String.Empty;
}

The event handler for the Save button has been enhanced to accommodate for new records. In the previous article, the Save button simply persisted the XmlDataProvider's XmlDocument to the underlying source XML file. That approach works well for update operations as any changes to the UI are automatically synchronized in the XmlDataProvider's XmlDocument through its binding. The enhanced event handler will search the XmlDataProvider's XmlDocument, using XPath, for the Team ID located in the TeamIDTextBox. If the ID is not found, the code builds the necessary XML nodes to represent the new team and then adds it to the XmlDataProvider's XmlDocument. Lastly, the XmlDataProvider's XmlDocument is persisted to the source XML file.

private void SaveTeamsButton_Click(object sender, RoutedEventArgs e)
{
     string source = TeamData.Source.LocalPath;

     // Get a handle on the source data file.
     XmlDocument doc = TeamData.Document;

     // Get a handle on the root node.
     XmlNode root = doc.SelectSingleNode("//Teams");

     // Attempt to find the Id in the data file.
     string xpath = "//Team[Id=" + TeamIDTextBox.Text + "]";
     XmlNode currentNode = root.SelectSingleNode(xpath);

     // If currentNode is null, then we add a new team with the data entered.  If found,
     // we simply call the save method to persist the updated data to the data file.
     if (currentNode == null)
     {
          XmlNode newTeam = doc.CreateElement("Team");
          XmlNode newTeamId = doc.CreateElement("Id");
          XmlNode newTeamName = doc.CreateElement("Name");
          XmlNode newTeamConference = doc.CreateElement("Conference");

          newTeamId.InnerText = TeamIDTextBox.Text;
          newTeamName.InnerText = TeamNameTextBox.Text;
          newTeamConference.InnerText = ConferenceTextBox.Text;

          newTeam.AppendChild(newTeamId);
          newTeam.AppendChild(newTeamName);
          newTeam.AppendChild(newTeamConference);

          root.AppendChild(newTeam);
     }

     // Save the changes.
     TeamData.Document.Save(source);
}

You will notice that the Delete button event handler looks familiar. It uses the same code as the Save button to find the currently selected record within the XmlDataProvider's XmlDocument. If found, the XmlNode that represents the current record is removed from the XmlDocument and the changes are persisted to the source XML file.

private void DeleteTeamsButton_Click(object sender, RoutedEventArgs e)
{
     // Get the physical path for saving later.
     string source = TeamData.Source.LocalPath;

     // Get a handle on the source data file.
     XmlDocument doc = TeamData.Document;

     // Get a handle on the root node.
     XmlNode root = doc.SelectSingleNode("//Teams");

     // Get the currently selected node within the source data file.
     string xpath = "//Team[Id=" + TeamIDTextBox.Text + "]";
     XmlNode currentNode = root.SelectSingleNode(xpath);

     if (currentNode != null)
     {
          // Delete the record.
          root.RemoveChild(currentNode);

          // Save the changes.
          TeamData.Document.Save(source);
     }
}

Conclusion

Even though the XmlDataProvider has its limitations, they can easily be overcome with a small amount of code. I hope that this article has been informative.

History

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