Infosys Microsoft Alliance and Solutions blog

« Why is the concept of a list so important in SharePoint | Main | Device Profile Web Service (DPWS) »

WPF - Updating XmlDataProvider when source XML changes

Some days back i had answered a question on the WPF Forum on how to ensure that when the base XML file changes, the XmlDataProvider is udpated and hence the bound control on the UI.

The key is to set a watch on the particular XML file for changes and then update the provider appropriately. See details here. This solution works fine, but I didn't particularly like my initial code that I wrote since the FileSystemWatcher was set externally. It would be better if this could be self contained within the XmlDataProvider itself.  

I hence decided to write my own XmlDataProvider for this purpose. Well, not write entirely, but obviously extend the existing provider. Following is the class that I wrote for this purpose. Since all I am really interested in is to get the FileSystemWatcher setup, I modify the Source property implementation and on the file change event, I force a refresh on the provider.

    public class MyXmlDataProvider : XmlDataProvider

    {

        public new Uri Source

        {

            get { return base.Source; }

            set

            {

                base.Source = value;

 

                FileSystemWatcher watcher = new FileSystemWatcher();

                //set the path of the XML file appropriately as per your requirements

                watcher.Path = AppDomain.CurrentDomain.BaseDirectory;

 

                //name of the file i am watching

                watcher.Filter = value.OriginalString;

 

                //watch for file changed events so that we can refresh the data provider

                watcher.Changed += new FileSystemEventHandler(file_Changed);

 

                //finally, don't forget to enable watching, else the events won't fire           

                watcher.EnableRaisingEvents = true;

            }

        }

 

        void file_Changed(object sender, FileSystemEventArgs e)

        {

            base.Refresh();

        }

    }

This is all that is required. Using this in XAML is pretty straightfoward and following is a sample XAML.

<Window x:Class="TestWPFApp.XmlRefreshTest"

   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

   xmlns:local="clr-namespace:TestWPFApp" 

   Title="XmlRefreshTest" Height="300" Width="300">

    <Window.Resources>

        <local:MyXmlDataProvider x:Key="xmlFromFile" Source="PersonXml.xml" XPath="persons/person" />

    </Window.Resources>

    <Grid>

        <ListView ItemsSource="{Binding Source={StaticResource xmlFromFile}}" x:Name="list" >

            <ListView.View>

                <GridView>

                    <GridViewColumn Header="FirstName" DisplayMemberBinding="{Binding XPath=@firstname}" />

                    <GridViewColumn Header="LastName" DisplayMemberBinding="{Binding XPath=@lastname}" />

                    <GridViewColumn Header="Age" DisplayMemberBinding="{Binding XPath=@age}" />

                </GridView>

            </ListView.View>

        </ListView>

    </Grid>

</Window>

For my testing, I used the following Xml file. Note that I had marked the Xml as Content and Copy if newer in its properties to ensure that the Xml file is available in the output directory.

<?xml version="1.0" encoding="utf-8" ?>

<persons xmlns="">

    <person firstname="Atul" lastname="Gupta" age="35" />

    <person firstname="Sidharth" lastname="Ghag" age="30" />

    <person firstname="Virendra" lastname="Wadekar" age="30" />

</persons>

Comments are welcome !

TrackBack

TrackBack URL for this entry:
http://www.infosysblogs.com/microsoft-mt/mt-tb.fcgi/203

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)