I'm creating a fully generic file explorer for AvaloniaUI. It has a view that shows a folder tree that you can navigate by expanding each directory.
My goal is to make this view flexible enough to support selecting multiple items from multiple nodes.
The problem? The tree is dynamic. Not only are the children lazily loaded, but also the user can potentially create new items (like folders), and select them.
- I currently have a
IFileIteminterface to represent the items in the file structure. I haveFolderandFilecurrently. - Folders can have other entries (folders + files), of course.
- Both File and Folder are ViewModels (even though I'm not adding the ViewModel suffix )
interface IFileItem
{
string Path { get; }
}
class Folder : IFileItem
{
ReadOnlyObservableCollection<IFileEntry> { get; }
...
}
class File : IFileItem
{
...
}
To support the selection feature, my plan is to add a property ReadOnlyObservableCollection<IFileItem> SelectedItems:
class Folder : IFileEntry
{
ReadOnlyObservableCollection<IFileItem> Children { get; }
bool IsSelected { get; set; }
ReadOnlyObservableCollection<IFileItem> SelectedItems { get; }
...
}
The SelectedItems property should hold a list of whatever it's selected in a given branch, this is, the given node + the children.
This approach could be useful, and might be what I need, but I'm not sure how well is this solution for supporting scenarios like single folder picking.
Now the question: How do we define the SelectedItems property???
It should watch change of this.IsSelected AND Children.IsSelected RECURSIVELY. Now that's hard. I'm not familiarized with any use case like this in DynamicData, but I think it should be handled. For now, I'm completely stuck.
I hope someone could come with a nice solution in a purely DD way :)
Here's partially implemented solution. It's a pain and it's got a fair bit of work to be fully functional, but this works for demonstrating how to maintain the
SelectedItemscollection at all of the levels.Start with the basic interface and abstract class:
I then implemented
File:And then
Folder:Now my test was done in LINQPad:
So even though
f7is nested belowf3andf3is belowf1it still appears and disappears inf1's collection.