Search code examples
c#wpfeventsdata-bindingfilesystemwatcher

using the FileSystemWatcher to dynamically alter the items in a combo box


OK, so I am trying to use the FileSystemWatcher to watch for changes in a directory and then dynamically change the items in a combo box. my populateCb() method works initially when the user control is loaded. and i added a break point inside the watcher changed event which breaks when i change the contents of the directory. so I know the events are being triggered and the watcher_Changed method is being called. but the contents of my combo-box do not change... What am I doing wrong?

public partial class HtmlViewer : UserControl
{
    private List<string> emails = new List<string>();
    FileSystemWatcher watcher = new FileSystemWatcher("emailTemplates", "*.msg");
    public HtmlViewer()
    {
        InitializeComponent();
        populateCb();
        watcher.Changed += watcher_Changed;
        watcher.Created += watcher_Changed;
        watcher.Deleted += watcher_Changed;
        watcher.Renamed += watcher_Changed;
        watcher.EnableRaisingEvents = true;

    }

    void watcher_Changed(object sender, FileSystemEventArgs e)
    {
        this.Dispatcher.Invoke((Action)(() =>
            {
                populateCb();
            }
            ));

    }
    private void populateCb()
    {
        emails.Clear();
        foreach(var file in Directory.EnumerateFiles("emailTemplates", "*.msg", SearchOption.AllDirectories))
        {
            emails.Add(file);
        }
        emailSelector.ItemsSource = emails;
    }
}

Solution

  • The simplest solution is to set the ItemSource to null before changing the List<string> emails

    private void populateCb()
    {
        emailSelector.ItemsSource = null;
        emails.Clear();
        foreach(var file in Directory.EnumerateFiles("emailTemplates", "*.msg", SearchOption.AllDirectories))
        {
            emails.Add(file);
        }
        emailSelector.ItemsSource = emails;
    }
    

    Without it you are not changing the previous ItemSource. It is the same object. The List<string> has no capability to notify the binding infrastructure of WPF of changes to its elements. So clearing the items, readding them is totally invisible to the ComboBox. Instead setting ItemSource = null, and then resetting it again informs the combobox of the changes.

    A possible (and probably better option) is to change your List to an ObservableCollection that has the capability to notifiy changes