views:

50

answers:

3

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;
+1  A: 

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

Michael
I see that FileSystemWatcher is not too good idea in my project and try INotifyCollectionCHanged ;) Thanks!
netmajor
So the changes are within your application and not by external programs changing a common file?
Michael
+1  A: 

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");
    }
Simon
I don't use Your advice in my project but thanks for info about this class, i test it and it really works, great watcher !!
netmajor
+1  A: 

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";
    }
}
Robert Rossney