Question

It's possible to implement INotifyCollectionChanged or other interface like IObservable to enable to bind filtered data from xml file on this file changed ? I see examples with properties or collection, but what with files changes ?

I have that code to filter and bind xml data to list box:

XmlDocument channelsDoc = new XmlDocument();
channelsDoc.Load("RssChannels.xml");
XmlNodeList channelsList = channelsDoc.GetElementsByTagName("channel");
this.RssChannelsListBox.DataContext = channelsList;
Was it helpful?

Solution

Try using a FileSystemWatcher

    private static void StartMonitoring()
    {
        //Watch the current directory for changes to the file RssChannels.xml
        var fileSystemWatcher = new FileSystemWatcher(@".\","RssChannels.xml");

        //What should happen when the file is changed
        fileSystemWatcher.Changed += fileSystemWatcher_Changed;

        //Start watching
        fileSystemWatcher.EnableRaisingEvents = true;
    }

    static void fileSystemWatcher_Changed(object sender, FileSystemEventArgs e)
    {
        Debug.WriteLine(e.FullPath + " changed");
    }

OTHER TIPS

You will have to implement INotifyCollectionChanged on your own, to watch for file system changes use the FileSystemWatcher class in System.IO

The XmlDocument already raises NodeChanged events. If you use an XmlDataProvider as your binding source, it listens to NodeChanged events and refreshes the bindings. It also refreshes the bindings if you change its Document property. Combine that with the FileSystemWatcher and you're on your way.

A simple example:

<Window x:Class="WpfApplication18.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <Window.Resources>
        <XmlDataProvider x:Key="Data" XPath="/Data">
            <x:XData>
                <Data xmlns="">
                    <Channel>foo</Channel>
                    <Channel>bar</Channel>
                    <Channel>baz</Channel>
                    <Channel>bat</Channel>
                </Data>
            </x:XData>
        </XmlDataProvider>
    </Window.Resources>
    <StackPanel Margin="50">
        <ListBox ItemsSource="{Binding Source={StaticResource Data}, XPath=Channel}" />
        <Button Margin="10" 
                Click="ReloadButton_Click">Reload</Button>
        <Button Margin="10"
                Click="UpdateButton_Click">Update</Button>
    </StackPanel>
</Window>

The event handlers:

private void ReloadButton_Click(object sender, RoutedEventArgs e)
{
    XmlDocument d = new XmlDocument();
    d.LoadXml(@"<Data xmlns=''><Channel>foobar</Channel><Channel>quux</Channel></Data>");
    XmlDataProvider p = Resources["Data"] as XmlDataProvider;
    p.Document = d;
}

private void UpdateButton_Click(object sender, RoutedEventArgs e)
{
    XmlDataProvider p = Resources["Data"] as XmlDataProvider;
    XmlDocument d = p.Document;
    foreach (XmlElement elm in d.SelectNodes("/Data/Channel"))
    {
        elm.InnerText = "Updated";
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top