Skip to content

SelectionModel: No way to react to a child collection being replaced #2404

@grokys

Description

@grokys

Describe the bug

If I have a SelectionModel over nested data, I use ChildrenRequested to get the child nodes of a particular node. Once I return the collection containing the child nodes, the SelectionNode listens for change notifications on this collection and updates the model accordingly

The problem comes when the child collection object is replaced on the source data. The SelectionModel is unaware of this and there's no way for it to be aware that the child collection has changed.

I believe this is a deficit in the design of SelectionModel.

Steps to reproduce the bug

Place the following in SelectionModelTests and run the test:

[TestMethod]
public void Can_Replace_Children_Collection()
{
	RunOnUIThread.Execute(() =>
	{
		var root = new Node("Root");
		var target = new SelectionModel { Source = new[] { root } };
		target.ChildrenRequested += (s, e) => e.Children = ((Node)e.Source).Children;

		// Select Root.Child9
		target.Select(0, 9);
		Verify.AreEqual("Child9", ((Node)target.SelectedItem).Header);

		// Replace Root children with collection with only 5 nodes.
		root.ReplaceChildren();

		// FAIL: Still references the old children
		Verify.IsNull(target.SelectedItem);
	});
}

private class Node : INotifyPropertyChanged
{
	private ObservableCollection<Node> _children;

	public Node(string header)
	{
		Header = header;
	}

	public string Header { get; }

	public ObservableCollection<Node> Children
	{
		get => _children ??= CreateChildren(10);
		private set
		{
			_children = value;
			PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Children)));
		}
	}

	public event PropertyChangedEventHandler PropertyChanged;

	public void ReplaceChildren()
	{
		Children = CreateChildren(5);
	}

	private ObservableCollection<Node> CreateChildren(int count)
	{
		return new ObservableCollection<Node>(
			Enumerable.Range(0, count).Select(x => new Node("Child" + x)));
	}
}

Expected behavior

The SelectionModel should have some mechanism to detect a change to the child collection.

Version Info

master (d14b639)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions