public static void SetSource(DependencyObject obj, FocusSource value)
    {
        if (obj is null)
        {
            throw new ArgumentNullException(nameof(obj));
        }

        obj.SetValue(SourceProperty, value);
    }
    public FilterDialogViewModel(
        Func <Task <IEnumerable <IHierarchyNode> > > hierarchyFactory,
        Func <TimeSpan, IDebouncer> debouncerFactory,
        TextFilterFactory textFilterFactory,
        JoinableTaskFactory joinableTaskFactory
        )
    {
        if (debouncerFactory is null)
        {
            throw new ArgumentNullException(nameof(debouncerFactory));
        }

        _hierarchyFactory  = hierarchyFactory ?? throw new ArgumentNullException(nameof(hierarchyFactory));
        _textFilterFactory = textFilterFactory ?? throw new ArgumentNullException(nameof(textFilterFactory));

        _items             = new HierarchyTreeViewItemCollection(Enumerable.Empty <HierarchyTreeViewItem>());
        _searchText        = "";
        _loadingVisibility = Visibility.Visible;
        _loadedVisibility  = Visibility.Collapsed;

        FocusSearchBoxSource = new FocusSource();

        ToggleLoadProjectDependenciesCommand = new DelegateCommand(
            (_) => LoadProjectDependencies   = !LoadProjectDependencies,
            CanAlwaysExecute,
            joinableTaskFactory
            );

        CollapseAllCommand = new DelegateCommand <HierarchyTreeViewItem>(
            CollapseAll,
            CanAlwaysExecute,
            joinableTaskFactory
            );

        ExpandAllCommand = new DelegateCommand <HierarchyTreeViewItem>(
            ExpandAll,
            CanAlwaysExecute,
            joinableTaskFactory
            );

        CheckAllCommand = new DelegateCommand(
            (_) => SetAllChecked(true),
            CanAlwaysExecute,
            joinableTaskFactory
            );

        UncheckAllCommand = new DelegateCommand(
            (_) => SetAllChecked(false),
            CanAlwaysExecute,
            joinableTaskFactory
            );

        ToggleRegularExpressionModeCommand = new DelegateCommand(
            (_) => UseRegularExpressions   = !UseRegularExpressions,
            CanAlwaysExecute,
            joinableTaskFactory
            );

        FocusSearchBoxCommand = new DelegateCommand(
            (_) => FocusSearchBoxSource.RequestFocus(),
            CanAlwaysExecute,
            joinableTaskFactory
            );

        AcceptCommand = new DelegateCommand(
            (_) => AcceptSelection(),
            CanAlwaysExecute,
            joinableTaskFactory
            );

        // Use a `DispatcherTimer` constructor without a callback
        // so that the timer doesn't start immediately. We only
        // want to start the timer when the search text changes.
        _debouncer         = debouncerFactory.Invoke(TimeSpan.FromMilliseconds(500));
        _debouncer.Stable += OnSearchStable;
    }