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.
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;
XmlDocument doc = TeamData.Document;
XmlNode root = doc.SelectSingleNode("//Teams");
string xpath = "//Team[Id=" + TeamIDTextBox.Text + "]";
XmlNode currentNode = root.SelectSingleNode(xpath);
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);
}
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)
{
string source = TeamData.Source.LocalPath;
XmlDocument doc = TeamData.Document;
XmlNode root = doc.SelectSingleNode("//Teams");
string xpath = "//Team[Id=" + TeamIDTextBox.Text + "]";
XmlNode currentNode = root.SelectSingleNode(xpath);
if (currentNode != null)
{
root.RemoveChild(currentNode);
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