Browse Source

Make remaining tests pass.

pull/4533/head
Steven Kirk 6 years ago
parent
commit
9c8376348c
  1. 30
      src/Avalonia.Controls/Primitives/SelectingItemsControl.cs
  2. 2
      src/Avalonia.Controls/Selection/SelectionModel.cs
  3. 12
      src/Avalonia.Controls/Utils/SelectedItemsSync.cs
  4. 46
      tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests_Multiple.cs
  5. 21
      tests/Avalonia.Controls.UnitTests/Selection/SelectionModelTests_Single.cs

30
src/Avalonia.Controls/Primitives/SelectingItemsControl.cs

@ -351,16 +351,30 @@ namespace Avalonia.Controls.Primitives
protected override void OnDataContextBeginUpdate()
{
base.OnDataContextBeginUpdate();
++_initializing;
//InternalBeginInit();
if (_selection is object)
{
_selection.Source = null;
}
}
/// <inheritdoc/>
protected override void OnDataContextEndUpdate()
{
base.OnDataContextEndUpdate();
--_initializing;
if (_selection is object && _initializing == 0)
{
_selection.Source = Items;
//InternalEndInit();
if (Items is null)
{
_selection.Clear();
_selectedItemsSync?.SelectedItems?.Clear();
}
}
}
protected override void OnInitialized()
@ -397,9 +411,17 @@ namespace Avalonia.Controls.Primitives
{
base.OnPropertyChanged(change);
if (change.Property == ItemsProperty && _initializing == 0 && _selection is object)
if (change.Property == ItemsProperty &&
_initializing == 0 &&
_selection is object)
{
_selection.Source = change.NewValue.GetValueOrDefault<IEnumerable>();
var newValue = change.NewValue.GetValueOrDefault<IEnumerable>();
_selection.Source = newValue;
if (newValue is null)
{
_selection.Clear();
}
}
}

2
src/Avalonia.Controls/Selection/SelectionModel.cs

@ -44,7 +44,7 @@ namespace Avalonia.Controls.Selection
throw new InvalidOperationException("Cannot change source while update is in progress.");
}
if (base.Source is object)
if (base.Source is object && value is object)
{
using var update = BatchUpdate();
update.Operation.SkipLostSelection = true;

12
src/Avalonia.Controls/Utils/SelectedItemsSync.cs

@ -76,20 +76,18 @@ namespace Avalonia.Controls.Utils
private void SyncSelectedItemsWithSelectionModel()
{
if (_selectionModel.Source is null)
{
return;
}
_updatingItems = true;
try
{
_selectedItems.Clear();
foreach (var i in SelectionModel.SelectedItems)
if (_selectionModel.Source is object)
{
_selectedItems.Add(i);
foreach (var i in _selectionModel.SelectedItems)
{
_selectedItems.Add(i);
}
}
}
finally

46
tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests_Multiple.cs

@ -517,7 +517,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
/// DataContext is in the process of changing.
/// </remarks>
[Fact]
public void Should_Not_Write_To_Old_DataContext()
public void Should_Not_Write_SelectedItems_To_Old_DataContext()
{
var vm = new OldDataContextViewModel();
var target = new TestSelector();
@ -553,6 +553,46 @@ namespace Avalonia.Controls.UnitTests.Primitives
Assert.Empty(target.SelectedItems);
}
/// <summary>
/// See <see cref="Should_Not_Write_SelectedItems_To_Old_DataContext"/>.
/// </summary>
[Fact]
public void Should_Not_Write_SelectionModel_To_Old_DataContext()
{
var vm = new OldDataContextViewModel();
var target = new TestSelector();
var itemsBinding = new Binding
{
Path = "Items",
Mode = BindingMode.OneWay,
};
var selectionBinding = new Binding
{
Path = "Selection",
Mode = BindingMode.OneWay,
};
// Bind Items and Selection to the VM.
target.Bind(TestSelector.ItemsProperty, itemsBinding);
target.Bind(TestSelector.SelectionProperty, selectionBinding);
// Set DataContext and SelectedIndex
target.DataContext = vm;
target.SelectedIndex = 1;
// Make sure selection is written to selection model
Assert.Equal(1, vm.Selection.SelectedIndex);
// Clear DataContext and ensure that selection is still set in model.
target.DataContext = null;
Assert.Equal(1, vm.Selection.SelectedIndex);
// Ensure target's SelectedItems is now clear.
Assert.Empty(target.SelectedItems);
}
[Fact]
public void Unbound_SelectedItems_Should_Be_Cleared_When_DataContext_Cleared()
{
@ -1459,6 +1499,8 @@ namespace Avalonia.Controls.UnitTests.Primitives
{
public static readonly new AvaloniaProperty<IList> SelectedItemsProperty =
SelectingItemsControl.SelectedItemsProperty;
public static readonly new DirectProperty<SelectingItemsControl, ISelectionModel> SelectionProperty =
SelectingItemsControl.SelectionProperty;
public TestSelector()
{
@ -1495,10 +1537,12 @@ namespace Avalonia.Controls.UnitTests.Primitives
{
Items = new List<string> { "foo", "bar" };
SelectedItems = new List<string>();
Selection = new SelectionModel<string>();
}
public List<string> Items { get; }
public List<string> SelectedItems { get; }
public SelectionModel<string> Selection { get; }
}
private class ItemContainer : Control, ISelectable

21
tests/Avalonia.Controls.UnitTests/Selection/SelectionModelTests_Single.cs

@ -175,7 +175,26 @@ namespace Avalonia.Controls.UnitTests.Selection
}
[Fact]
public void Changing_Source_First_Clears_Old_Selection()
public void Changing_Source_To_Null_Doesnt_Clear_Selection()
{
var target = CreateTarget();
var raised = 0;
target.SelectedIndex = 2;
target.SelectionChanged += (s, e) => ++raised;
target.Source = null;
Assert.Equal(2, target.SelectedIndex);
Assert.Equal(new[] { 2 }, target.SelectedIndexes);
Assert.Null(target.SelectedItem);
Assert.Equal(new string?[] { null }, target.SelectedItems);
Assert.Equal(0, raised);
}
[Fact]
public void Changing_Source_To_NonNUll_First_Clears_Old_Selection()
{
var target = CreateTarget();
var raised = 0;

Loading…
Cancel
Save