Browse Source

Handle null SelectionModel.Source.

pull/3470/head
Steven Kirk 6 years ago
parent
commit
04f8516c32
  1. 20
      src/Avalonia.Controls/SelectionModel.cs
  2. 28
      src/Avalonia.Controls/SelectionModelChangeSet.cs
  3. 7
      src/Avalonia.Controls/SelectionNode.cs
  4. 42
      tests/Avalonia.Controls.UnitTests/SelectionModelTests.cs

20
src/Avalonia.Controls/SelectionModel.cs

@ -36,13 +36,29 @@ namespace Avalonia.Controls
get => _rootNode?.Source;
set
{
using (var operation = new Operation(this))
var wasNull = _rootNode.Source == null;
if (_rootNode.Source != null)
{
ClearSelection(resetAnchor: true);
using (var operation = new Operation(this))
{
ClearSelection(resetAnchor: true);
}
}
_rootNode.Source = value;
RaisePropertyChanged("Source");
if (wasNull)
{
var e = new SelectionModelSelectionChangedEventArgs(
null,
SelectedIndices,
null,
SelectedItems);
OnSelectionChanged(e);
}
}
}

28
src/Avalonia.Controls/SelectionModelChangeSet.cs

@ -16,30 +16,38 @@ namespace Avalonia.Controls
public SelectionModelSelectionChangedEventArgs CreateEventArgs()
{
var deselectedCount = 0;
var selectedCount = 0;
var deselectedIndexCount = 0;
var selectedIndexCount = 0;
var deselectedItemCount = 0;
var selectedItemCount = 0;
foreach (var change in _changes)
{
deselectedCount += change.DeselectedCount;
selectedCount += change.SelectedCount;
deselectedIndexCount += change.DeselectedCount;
selectedIndexCount += change.SelectedCount;
if (change.Items != null)
{
deselectedItemCount += change.DeselectedCount;
selectedItemCount += change.SelectedCount;
}
}
var deselectedIndices = new SelectedItems<IndexPath, SelectionNodeOperation>(
_changes,
deselectedCount,
deselectedIndexCount,
GetDeselectedIndexAt);
var selectedIndices = new SelectedItems<IndexPath, SelectionNodeOperation>(
_changes,
selectedCount,
selectedIndexCount,
GetSelectedIndexAt);
var deselectedItems = new SelectedItems<object?, SelectionNodeOperation>(
_changes,
deselectedCount,
deselectedItemCount,
GetDeselectedItemAt);
var selectedItems = new SelectedItems<object?, SelectionNodeOperation>(
_changes,
selectedCount,
selectedItemCount,
GetSelectedItemAt);
return new SelectionModelSelectionChangedEventArgs(
@ -71,7 +79,7 @@ namespace Avalonia.Controls
List<SelectionNodeOperation> infos,
int index)
{
static int GetCount(SelectionNodeOperation info) => info.DeselectedCount;
static int GetCount(SelectionNodeOperation info) => info.Items != null ? info.DeselectedCount : 0;
static List<IndexRange>? GetRanges(SelectionNodeOperation info) => info.DeselectedRanges;
return GetItemAt(infos, index, GetCount, GetRanges);
}
@ -80,7 +88,7 @@ namespace Avalonia.Controls
List<SelectionNodeOperation> infos,
int index)
{
static int GetCount(SelectionNodeOperation info) => info.SelectedCount;
static int GetCount(SelectionNodeOperation info) => info.Items != null ? info.SelectedCount : 0;
static List<IndexRange>? GetRanges(SelectionNodeOperation info) => info.SelectedRanges;
return GetItemAt(infos, index, GetCount, GetRanges);
}

7
src/Avalonia.Controls/SelectionNode.cs

@ -48,8 +48,11 @@ namespace Avalonia.Controls
{
if (_source != value)
{
ClearSelection();
UnhookCollectionChangedHandler();
if (_source != null)
{
ClearSelection();
UnhookCollectionChangedHandler();
}
_source = value;

42
tests/Avalonia.Controls.UnitTests/SelectionModelTests.cs

@ -1424,6 +1424,48 @@ namespace Avalonia.Controls.UnitTests
Assert.Equal(2, raised);
}
[Fact]
public void Raises_SelectionChanged_With_No_Source()
{
var target = new SelectionModel();
var raised = 0;
target.SelectionChanged += (s, e) =>
{
Assert.Empty(e.DeselectedIndices);
Assert.Empty(e.DeselectedItems);
Assert.Equal(new[] { new IndexPath(1) }, e.SelectedIndices);
Assert.Empty(e.SelectedItems);
++raised;
};
target.Select(1);
Assert.Equal(new[] { new IndexPath(1) }, target.SelectedIndices);
Assert.Empty(target.SelectedItems);
}
[Fact]
public void Raises_SelectionChanged_With_Items_After_Source_Is_Set()
{
var target = new SelectionModel();
var raised = 0;
target.Select(1);
target.SelectionChanged += (s, e) =>
{
Assert.Empty(e.DeselectedIndices);
Assert.Empty(e.DeselectedItems);
Assert.Equal(new[] { new IndexPath(1) }, e.SelectedIndices);
Assert.Equal(new[] { "bar" }, e.SelectedItems);
++raised;
};
target.Source = new[] { "foo", "bar", "baz" };
Assert.Equal(1, raised);
}
private int GetSubscriberCount(AvaloniaList<object> list)
{
return ((INotifyCollectionChangedDebug)list).GetCollectionChangedSubscribers()?.Length ?? 0;

Loading…
Cancel
Save