How do I remove treeviewitem using MVVM pattern?

I’m making a file explorer app using MVVM pattern in C# WPF. Right now I want to implement watcher events that are responsible for adding, removing and renaming items from treeview. I already have adding, and partially renaming (I think that in this case I have to combine deleting and adding). I’m struggling with deletion.

Deleted files are stil in the treeview. For example, Folder shouldn’t exist anymore, because I deleted it.

App window

I would very much appreciate help from You. Here’s a code I’ve written in class DirectoryInfoViewModel

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Forms;

namespace ViewModels {
    public class DirectoryInfoViewModel : FileSystemInfoViewModel
    {
        public ObservableCollection<FileSystemInfoViewModel> Items { get; private set; }  = new ObservableCollection<FileSystemInfoViewModel>();

        public bool Open(string path)
        {
            bool result = false;
           
            try
            {
                FileSystemWatcher Watcher = new FileSystemWatcher(path);
                Watcher.Created += OnFileCreated;
                Watcher.Renamed += OnFileRenamed;
                Watcher.Deleted += OnFileDeleted;
                //Watcher.Changed += OnFileChanged;
                Watcher.Error += Watcher_Error;
                Watcher.EnableRaisingEvents = true;

                foreach (var dirName in Directory.GetDirectories(path))
                {
                    var dirInfo = new DirectoryInfo(dirName);
                    DirectoryInfoViewModel itemViewModel = new DirectoryInfoViewModel
                    {
                        Model = dirInfo
                    };
                    itemViewModel.Open(dirName);
                    Items.Add(itemViewModel);
                }


                foreach (var fileName in Directory.GetFiles(path))
                {
                    var fileInfo = new FileInfo(fileName);
                    FileInfoViewModel itemViewModel = new FileInfoViewModel();
                    itemViewModel.Model = fileInfo;
                    Items.Add(itemViewModel);
                }
                result = true;
            }
            catch (Exception ex)
            {
                Exception = ex;
            }
            return result;
        }

        public Exception Exception { get; private set; }

  


        private static void Watcher_Error(object sender, ErrorEventArgs e) =>
            System.Windows.MessageBox.Show(e.GetException().ToString());


        public void OnFileCreated(object sender, FileSystemEventArgs e)
        {
            System.Windows.Application.Current.Dispatcher.Invoke(() => OnFileCreated(e));
        }

        private void OnFileCreated(FileSystemEventArgs e)
        {
            Debug.WriteLine("File Created: " + e.Name);
            if (!Items.Any(x => x.Caption == e.Name))
            {
                var dirInfo = new DirectoryInfo(e.FullPath);
                DirectoryInfoViewModel itemViewModel = new DirectoryInfoViewModel();
                itemViewModel.Model = dirInfo;
                Items.Add(itemViewModel);
            }
        }


        public void OnFileDeleted(object sender, FileSystemEventArgs e)
        {
            System.Windows.Application.Current.Dispatcher.Invoke(() => OnFileDeleted(e));
        }

        

        private void OnFileDeleted(FileSystemEventArgs e)
        {
            
                Debug.WriteLine("File Deleted: " + e.Name);
            if (Items.Any(x => x.Caption == e.Name))
            {
                var dirInfo = new DirectoryInfo(e.FullPath);
                Debug.WriteLine("File path: " + e.FullPath);
                DirectoryInfoViewModel itemViewModel = new DirectoryInfoViewModel();

                itemViewModel.Model = dirInfo;
                Items.Remove(itemViewModel);
              
            }


        }

        public void OnFileRenamed(object sender, FileSystemEventArgs e)
        {
            System.Windows.Application.Current.Dispatcher.Invoke(() => OnFileRenamed(e));
        }

        private void OnFileRenamed(FileSystemEventArgs e)
        {

            Debug.WriteLine("File Renamed: " + e.Name);

            OnFileDeleted(e);
            OnFileCreated(e);
     
        }
    } }

Answer

In private void OnFileDeleted(FileSystemEventArgs e) you create a new DirectoryInfoViewModel and attempt to remove it from the Items collection. ObservableCollection<T>.Remove(T) removes item based on a reference equality check if T does not provide an alternative equality check.

So you attempt to remove an item from for you Items collection which is not in the collection. If you check the return value of Items.Remove(itemViewModel) you will see that it returns false as no item equal to itemViewModel was found in the collection (see Collection.Remove(T)).

This would fix the problem by finding the item you want to remove and then removing it.

private void OnFileDeleted(FileSystemEventArgs e)
{
    if (Items.Any(x => x.Caption == e.Name))
    {
        var toDelete = Items.Single(x => x.Caption == e.Name);
        Items.Remove(toDelete);
    }
}