Home > Software design >  How to update one ObservableCollection<T> when a second ObservableCollection<T> has chan
How to update one ObservableCollection<T> when a second ObservableCollection<T> has chan

Time:11-15

I have two DataGrids "DG1" and "DG2" and two custom classes "TxtFiles" and "MFiles". I'm using the FileSystemWatcher class to monitor two directories. I assign the loaded data from a directory to ObservableCollection<FileFinfo>. Until now it all works fine. After that I manipulate the data and pass it to another ObservableCollection<TxtFiles> which I then want to be displayed in my DataGrid DG1 (I do the same with the second directory and DG2 and my "MFiles" class). However, the DataGrids are not updated when files are added or deleted in the directories.

My XAML Code:

    <Grid>
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition/>
        <RowDefinition/>
    </Grid.RowDefinitions>

    <DataGrid x:Name="DG1"/>
    <DataGrid x:Name="DG2" Grid.Row="1"/>

    <Button Content="Execute" Grid.Row="2"/>
</Grid>

TxtFiles Class:

    public class TxtFiles
{
    public string Name { get; set; }
    public string No1 { get; set; }
    public string No2 { get; set; }
    public string No3 { get; set; }

    public TxtFiles(string name, string n01, string no2, string no3) 
    { 
        Name = name;
        No1 = n01;
        No2 = no2;
        No3 = no3;
    
    }
}

FileWatcher class:

    internal class FileWatcher
{
    private readonly object filesLock = new object();

    private ObservableCollection<FileInfo> _files = new ObservableCollection<FileInfo>();
    public ObservableCollection<FileInfo> Files
    {
        get
        {
            return _files;
        }
        set
        {
            _files = value;
        }
    }

    public FileWatcher(string path)
    {
        BindingOperations.EnableCollectionSynchronization(Files, filesLock);

        lock (filesLock)
        {
            foreach (var fileInfo in new DirectoryInfo(path).EnumerateFiles())
            {
                Files.Add(fileInfo);
            }
        }

        var fsw = new FileSystemWatcher(path);
        fsw.Created  = FileCreated;
        fsw.Deleted  = FileDeleted;
        fsw.EnableRaisingEvents = true;
    }

    private void FileCreated(object sender, FileSystemEventArgs e)
    {
        lock (filesLock)
        {
            Files.Add(new FileInfo(e.Name));
        }
    }

    private void FileDeleted(object sender, FileSystemEventArgs e)
    {
        var removed = Files.FirstOrDefault(fi => fi.Name == e.Name);

        if (removed != null)
        {
            lock (filesLock)
            {
                Files.Remove(removed);
            }
        }
    }
}

My Code behind:

public partial class MainWindow : Window
{
    ObservableCollection<TxtFiles> TFiles = new ObservableCollection<TxtFiles>();
    ObservableCollection<MFiles> M_Files = new ObservableCollection<MFiles>();

    ObservableCollection<FileInfo> LoadedFiles1 = new ObservableCollection<FileInfo>();

    public MainWindow()
    {
        InitializeComponent();
        LoadedFiles1 = new FileWatcher("C:\\User\\").Files;

        foreach (FileInfo file in LoadedFiles1)
        {
            TFiles.Add(FileInfoToTxtFiles(file.Name));
        }

        DG1.ItemsSource = TFiles;

       //LoadedFiles1.CollectionChanged  = LoadedFiles_CollectionChanged;


    }


    //Convert loaded directory files into TxTFiles 
    public static TxtFiles FileInfoToTxtFiles(string file)
    {
        string[] temp = file.ToString().Split('_', '.');
        TxtFiles txtFile = new TxtFiles(temp[0], temp[1], temp[2], temp[3]);
        return txtFile;
    }



    //private void LoadedFiles_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    //{
    //    foreach(var file in e.NewItems)
    //    {
    //        TFiles.Add(FileInfoToTxtFiles(file));
    //    }
    //}


}

I tried using the CollectionChanged event of the ObservableCollection but didn't succeed. Maybe someone has a tip? Thanks very much!

CodePudding user response:

The ObservableCollection<FileInfo> in the FileWatcher will raise a CollectionChanged event when a file is added or removed.

You could handle this event and add and remove TxtFiles from the ObservableCollection<TxtFiles>:

public MainWindow()
{
    InitializeComponent();
    LoadedFiles1 = new FileWatcher("C:\\User\\").Files;

    foreach (FileInfo file in LoadedFiles1)
    {
        TFiles.Add(FileInfoToTxtFiles(file.Name));
    }

    LoadedFiles1.CollectionChanged  = (s, e) =>
    {
        if (e.NewItems != null)
            foreach (var addedItem in e.NewItems.OfType<FileInfo>())
                TFiles.Add(FileInfoToTxtFiles(addedItem.Name));

        if (e.OldItems != null)
            foreach (var removedItems in e.OldItems.OfType<FileInfo>())
            {
                var tFile = ...;
                TFiles.Remove(Tfile);
            }
    };

    DG1.ItemsSource = TFiles;
}

You will have to figure out how to find the corresponding TxtFiles object to be removed.

  • Related