private async Task NewFolder(IBuildFolderViewModel folder)
        {
            var name = await _dialogCoordinator.ShowValidatingInputDialogAsync(this,
                                                                               L10n.Message("New Folder"),
                                                                               L10n.Message("Enter the name of the new folder."),
                                                                               "",
                                                                               s => _buildValidator.ValidateNewFolderName(s, folder));

            if (string.IsNullOrWhiteSpace(name))
            {
                return;
            }
            var newFolder = new BuildFolderViewModel(new BuildFolder {
                Name = name
            }, Filter, BuildOnCollectionChanged);

            folder.Children.Add(newFolder);
            await SaveBuildToFile(newFolder);
        }
        public BuildsControlViewModel(IExtendedDialogCoordinator dialogCoordinator, IPersistentData persistentData, ISkillTree skillTree)
        {
            _dialogCoordinator = dialogCoordinator;
            PersistentData     = persistentData;
            DropHandler        = new CustomDropHandler(this);
            _buildValidator    = new BuildValidator(PersistentData.Options);
            BuildRoot          = new BuildFolderViewModel(persistentData.RootBuild, Filter, BuildOnCollectionChanged);

            _fileSystemWatcher = new FileSystemWatcher
            {
                Path = PersistentData.Options.BuildsSavePath,
                IncludeSubdirectories = true,
                NotifyFilter          = NotifyFilters.DirectoryName | NotifyFilters.FileName | NotifyFilters.LastWrite
            };
            _fileSystemWatcher.Error              += FileSystemWatcherOnError;
            _fileSystemWatcher.Changed            += FileSystemWatcherOnChanged;
            _fileSystemWatcher.Created            += FileSystemWatcherOnChanged;
            _fileSystemWatcher.Deleted            += FileSystemWatcherOnChanged;
            _fileSystemWatcher.Renamed            += FileSystemWatcherOnChanged;
            _fileSystemWatcher.EnableRaisingEvents = true;

            // The monitor alone is not enough because delays are necessary and those shouldn't block other save
            // operations, which would happen if delays are awaited directly in the save method.
            // It could be done awaited with .ConfigureAwait(false) if SimpleMonitor would be thread safe.
            _changingFileSystemMonitor.Entered += (sender, args) => _changingFileSystemCounter++;
            _changingFileSystemMonitor.Freed   += async(sender, args) =>
            {
                // Wait because FileSystemWatcherOnChanged calls are delayed a bit.
                await Task.Delay(2000);

                // This is a counter and not boolean because other save operations may happen while waiting on delay.
                _changingFileSystemCounter--;
            };

            CurrentBuild  = TreeFindBuildViewModel(PersistentData.CurrentBuild);
            SelectedBuild = TreeFindBuildViewModel(PersistentData.SelectedBuild);
            PersistentData.PropertyChanged         += PersistentDataOnPropertyChanged;
            PersistentData.Options.PropertyChanged += OptionsOnPropertyChanged;

            NewFolderCommand = new AsyncRelayCommand <IBuildFolderViewModel>(
                NewFolder,
                vm => vm != null && _buildValidator.CanHaveSubfolder(vm));
            NewBuildCommand = new RelayCommand <IBuildFolderViewModel>(NewBuild);
            DeleteCommand   = new AsyncRelayCommand <IBuildViewModel>(
                Delete,
                o => o != BuildRoot);
            OpenBuildCommand = new AsyncRelayCommand <BuildViewModel>(
                OpenBuild,
                b => b != null && (b != CurrentBuild || b.Build.IsDirty));
            SaveBuildCommand = new AsyncRelayCommand <BuildViewModel>(
                SaveBuild,
                b => b != null && b.Build.IsDirty);
            SaveBuildAsCommand   = new AsyncRelayCommand <BuildViewModel>(SaveBuildAs);
            SaveAllBuildsCommand = new AsyncRelayCommand(
                SaveAllBuilds,
                () => TreeFind <BuildViewModel>(b => b.Build.IsDirty, BuildRoot) != null);
            RevertBuildCommand = new RelayCommand <BuildViewModel>(
                build => build.Build.RevertChanges(),
                b => b != null && b.Build.IsDirty && b.Build.CanRevert);
            MoveUpCommand = new RelayCommand <IBuildViewModel>(
                MoveUp,
                o => o != BuildRoot && o.Parent.Children.IndexOf(o) > 0);
            MoveDownCommand = new RelayCommand <IBuildViewModel>(
                MoveDown,
                o => o != BuildRoot && o.Parent.Children.IndexOf(o) < o.Parent.Children.Count - 1);
            EditCommand = new AsyncRelayCommand <IBuildViewModel>(Edit);
            CutCommand  = new AsyncRelayCommand <IBuildViewModel>(
                Cut,
                b => b != BuildRoot && b != CurrentBuild);
            CopyCommand                       = new RelayCommand <IBuildViewModel <PoEBuild> >(Copy);
            PasteCommand                      = new AsyncRelayCommand <IBuildViewModel>(Paste, CanPaste);
            ReloadCommand                     = new AsyncRelayCommand(Reload);
            OpenBuildsSavePathCommand         = new RelayCommand(() => Process.Start(PersistentData.Options.BuildsSavePath));
            ExpandAllCommand                  = new RelayCommand(ExpandAll);
            CollapseAllCommand                = new RelayCommand(CollapseAll);
            ExportCurrentToClipboardCommand   = new RelayCommand(() => CopyToClipboard(CurrentBuild.Build));
            ImportCurrentFromClipboardCommand = new AsyncRelayCommand(ImportCurrentFromClipboard, CanPasteFromClipboard);

            ExportGGGBuildFile = new RelayCommand <IBuildFolderViewModel>(ExportGGGBuild);
            ImportGGGBuildFile = new RelayCommand(() => ImportGGGBuild());

            SkillTree        = skillTree;
            ClassFilterItems = GenerateAscendancyClassItems(SkillTree.AscendancyClasses).ToList();
            ClassFilter      = NoFilterItem;
        }