|
@@ -8,6 +8,7 @@ using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Collections.Generic;
|
|
using System.Collections.Specialized;
|
|
using System.Collections.Specialized;
|
|
using System.Linq;
|
|
using System.Linq;
|
|
|
|
+using Avalonia.Controls.Utils;
|
|
|
|
|
|
#nullable enable
|
|
#nullable enable
|
|
|
|
|
|
@@ -214,7 +215,21 @@ namespace Avalonia.Controls
|
|
|
|
|
|
public void SetChildrenObservable(IObservable<object?> resolver)
|
|
public void SetChildrenObservable(IObservable<object?> resolver)
|
|
{
|
|
{
|
|
- _childrenSubscription = resolver.Subscribe(x => Source = x);
|
|
|
|
|
|
+ _childrenSubscription = resolver.Subscribe(x =>
|
|
|
|
+ {
|
|
|
|
+ if (Source != null)
|
|
|
|
+ {
|
|
|
|
+ using (_manager.Update())
|
|
|
|
+ {
|
|
|
|
+ SelectionTreeHelper.Traverse(
|
|
|
|
+ this,
|
|
|
|
+ realizeChildren: false,
|
|
|
|
+ info => info.Node.Clear());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Source = x;
|
|
|
|
+ });
|
|
}
|
|
}
|
|
|
|
|
|
public int SelectedCount { get; private set; }
|
|
public int SelectedCount { get; private set; }
|
|
@@ -544,11 +559,14 @@ namespace Avalonia.Controls
|
|
|
|
|
|
private void ClearChildNodes()
|
|
private void ClearChildNodes()
|
|
{
|
|
{
|
|
- foreach (var child in _childrenNodes)
|
|
|
|
|
|
+ for (int i = 0; i < _childrenNodes.Count; i++)
|
|
{
|
|
{
|
|
|
|
+ var child = _childrenNodes[i];
|
|
|
|
+
|
|
if (child != null && child != _manager.SharedLeafNode)
|
|
if (child != null && child != _manager.SharedLeafNode)
|
|
{
|
|
{
|
|
child.Dispose();
|
|
child.Dispose();
|
|
|
|
+ _childrenNodes[i] = null;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -713,101 +731,67 @@ namespace Avalonia.Controls
|
|
var selectionInvalidated = false;
|
|
var selectionInvalidated = false;
|
|
var removed = new List<object?>();
|
|
var removed = new List<object?>();
|
|
var count = items.Count;
|
|
var count = items.Count;
|
|
-
|
|
|
|
- // Remove the items from the selection for leaf
|
|
|
|
- if (ItemsSourceView!.Count > 0)
|
|
|
|
- {
|
|
|
|
- bool isSelected = false;
|
|
|
|
|
|
+ var isSelected = false;
|
|
|
|
|
|
- for (int i = 0; i <= count - 1; i++)
|
|
|
|
|
|
+ for (int i = 0; i <= count - 1; i++)
|
|
|
|
+ {
|
|
|
|
+ if (IsSelected(index + i))
|
|
{
|
|
{
|
|
- if (IsSelected(index + i))
|
|
|
|
- {
|
|
|
|
- isSelected = true;
|
|
|
|
- removed.Add(items[i]);
|
|
|
|
- }
|
|
|
|
|
|
+ isSelected = true;
|
|
|
|
+ removed.Add(items[i]);
|
|
}
|
|
}
|
|
|
|
+ }
|
|
|
|
|
|
- if (isSelected)
|
|
|
|
- {
|
|
|
|
- var removeRange = new IndexRange(index, index + count - 1);
|
|
|
|
- SelectedCount -= IndexRange.Remove(_selected, removeRange);
|
|
|
|
- selectionInvalidated = true;
|
|
|
|
-
|
|
|
|
- if (_selectedItems != null)
|
|
|
|
- {
|
|
|
|
- foreach (var i in items)
|
|
|
|
- {
|
|
|
|
- _selectedItems.Remove(i);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ if (isSelected)
|
|
|
|
+ {
|
|
|
|
+ var removeRange = new IndexRange(index, index + count - 1);
|
|
|
|
+ SelectedCount -= IndexRange.Remove(_selected, removeRange);
|
|
|
|
+ selectionInvalidated = true;
|
|
|
|
|
|
- for (int i = 0; i < _selected.Count; i++)
|
|
|
|
|
|
+ if (_selectedItems != null)
|
|
{
|
|
{
|
|
- var range = _selected[i];
|
|
|
|
-
|
|
|
|
- // The range is after the removed items, need to shift the range left
|
|
|
|
- if (range.End > index)
|
|
|
|
|
|
+ foreach (var i in items)
|
|
{
|
|
{
|
|
- // Shift the range to the left
|
|
|
|
- _selected[i] = new IndexRange(range.Begin - count, range.End - count);
|
|
|
|
- selectionInvalidated = true;
|
|
|
|
|
|
+ _selectedItems.Remove(i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ }
|
|
|
|
|
|
- // Update for non-leaf if we are tracking non-leaf nodes
|
|
|
|
- if (_childrenNodes.Count > 0)
|
|
|
|
- {
|
|
|
|
- selectionInvalidated = true;
|
|
|
|
- for (int i = 0; i < count; i++)
|
|
|
|
- {
|
|
|
|
- if (_childrenNodes[index] != null)
|
|
|
|
- {
|
|
|
|
- removed.AddRange(_childrenNodes[index]!.SelectedItems);
|
|
|
|
- RealizedChildrenNodeCount--;
|
|
|
|
- _childrenNodes[index]!.Dispose();
|
|
|
|
- }
|
|
|
|
- _childrenNodes.RemoveAt(index);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ for (int i = 0; i < _selected.Count; i++)
|
|
|
|
+ {
|
|
|
|
+ var range = _selected[i];
|
|
|
|
|
|
- //Adjust the anchor
|
|
|
|
- if (AnchorIndex >= index)
|
|
|
|
|
|
+ // The range is after the removed items, need to shift the range left
|
|
|
|
+ if (range.End > index)
|
|
{
|
|
{
|
|
- AnchorIndex -= count;
|
|
|
|
|
|
+ // Shift the range to the left
|
|
|
|
+ _selected[i] = new IndexRange(range.Begin - count, range.End - count);
|
|
|
|
+ selectionInvalidated = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- else
|
|
|
|
- {
|
|
|
|
- // No more items in the list, clear
|
|
|
|
- ClearSelection();
|
|
|
|
- RealizedChildrenNodeCount = 0;
|
|
|
|
- selectionInvalidated = true;
|
|
|
|
- }
|
|
|
|
|
|
|
|
- // Check if removing a node invalidated an ancestors
|
|
|
|
- // selection state. For example if parent was partially selected before
|
|
|
|
- // removing an item, it could be selected now.
|
|
|
|
- if (!selectionInvalidated)
|
|
|
|
|
|
+ // Update for non-leaf if we are tracking non-leaf nodes
|
|
|
|
+ if (_childrenNodes.Count > 0)
|
|
{
|
|
{
|
|
- var parent = _parent;
|
|
|
|
-
|
|
|
|
- while (parent != null)
|
|
|
|
|
|
+ selectionInvalidated = true;
|
|
|
|
+ for (int i = 0; i < count; i++)
|
|
{
|
|
{
|
|
- var isSelected = parent.IsSelectedWithPartial();
|
|
|
|
- // If a parent is partially selected, then it will become selected.
|
|
|
|
- // If it is selected or not selected - there is no change.
|
|
|
|
- if (!isSelected.HasValue)
|
|
|
|
|
|
+ if (_childrenNodes[index] != null)
|
|
{
|
|
{
|
|
- selectionInvalidated = true;
|
|
|
|
- break;
|
|
|
|
|
|
+ removed.AddRange(_childrenNodes[index]!.SelectedItems);
|
|
|
|
+ RealizedChildrenNodeCount--;
|
|
|
|
+ _childrenNodes[index]!.Dispose();
|
|
}
|
|
}
|
|
-
|
|
|
|
- parent = parent._parent;
|
|
|
|
|
|
+ _childrenNodes.RemoveAt(index);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ //Adjust the anchor
|
|
|
|
+ if (AnchorIndex >= index)
|
|
|
|
+ {
|
|
|
|
+ AnchorIndex -= count;
|
|
|
|
+ }
|
|
|
|
+
|
|
return (selectionInvalidated, removed);
|
|
return (selectionInvalidated, removed);
|
|
}
|
|
}
|
|
|
|
|