Skip to content

Commit

Permalink
ItemsRepeaterExtensions fixes (#538)
Browse files Browse the repository at this point in the history
  • Loading branch information
Xiaoy312 committed Apr 17, 2023
1 parent bb715a0 commit e38ebad
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ private Shell BuildShell()
AddNavigationItems(nv);

// landing navigation
ShellNavigateTo<TabBarBehaviorSamplePage>(
ShellNavigateTo<RuntimeTestRunner>(
#if WINDOWS_UWP
// note: on uwp, NavigationView.SelectedItem MUST be set on launch to avoid entering compact-mode
trySynchronizeCurrentItem: true
Expand Down
8 changes: 4 additions & 4 deletions src/Uno.Toolkit.RuntimeTests/Tests/ItemsRepeaterChipTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ public async Task MultiToSingle_Selected_ShouldPreserveFirstSelection()

#endregion

private static ItemsRepeater SetupItemsRepeater(object source, ItemsSelectionMode mode)
internal static ItemsRepeater SetupItemsRepeater(object source, ItemsSelectionMode mode)
{
var SUT = new ItemsRepeater
{
Expand All @@ -162,22 +162,22 @@ private static ItemsRepeater SetupItemsRepeater(object source, ItemsSelectionMod
return SUT;
}

private static bool? IsChipSelectedAt(ItemsRepeater ir, int index)
internal static bool? IsChipSelectedAt(ItemsRepeater ir, int index)
{
return (ir.TryGetElement(index) as ChipControl)?.IsChecked;
}

// since we are not using IsThreeState=True, the values can only be true/false.
// if any of them is null, that means there is another problem and should be thrown.
// therefore, only == check should be used in an assertion.
private static bool?[] GetChipsSelectionState(ItemsRepeater ir)
internal static bool?[] GetChipsSelectionState(ItemsRepeater ir)
{
return (ir.ItemsSource as IEnumerable)?.Cast<object>()
.Select((_, i) => (ir.TryGetElement(i) as ChipControl)?.IsChecked)
.ToArray() ?? new bool?[0];
}

private static void FakeTapItemAt(ItemsRepeater ir, int index)
internal static void FakeTapItemAt(ItemsRepeater ir, int index)
{
if (ir.TryGetElement(index) is { } element)
{
Expand Down
43 changes: 43 additions & 0 deletions src/Uno.Toolkit.RuntimeTests/Tests/ItemsRepeaterExtensionTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Windows.UI.Xaml;
using Uno.Toolkit.RuntimeTests.Helpers;
using Uno.Toolkit.UI;
using Uno.UI.RuntimeTests;
using ItemsRepeater = Microsoft.UI.Xaml.Controls.ItemsRepeater;
using static Uno.Toolkit.RuntimeTests.Tests.ItemsRepeaterChipTests; // to borrow helper methods

namespace Uno.Toolkit.RuntimeTests.Tests;

[TestClass]
[RunsOnUIThread]
internal class ItemsRepeaterExtensionTests
{
[TestMethod]
[DataRow(nameof(ItemsRepeaterExtensions.SelectedItemProperty))]
[DataRow(nameof(ItemsRepeaterExtensions.SelectedItemsProperty))]
[DataRow(nameof(ItemsRepeaterExtensions.SelectedIndexProperty))]
[DataRow(nameof(ItemsRepeaterExtensions.SelectedIndexesProperty))]
public async Task When_Selection_Property_Changed(string property)
{
var source = Enumerable.Range(0, 3).ToList();
var SUT = SetupItemsRepeater(source, ItemsSelectionMode.SingleOrNone);
await UnitTestUIContentHelperEx.SetContentAndWait(SUT);

(property switch
{
nameof(ItemsRepeaterExtensions.SelectedItemProperty) => () => ItemsRepeaterExtensions.SetSelectedItem(SUT, source.ElementAt(1)),
nameof(ItemsRepeaterExtensions.SelectedItemsProperty) => () => ItemsRepeaterExtensions.SetSelectedItems(SUT, new object[] { 1 }),
nameof(ItemsRepeaterExtensions.SelectedIndexProperty) => () => ItemsRepeaterExtensions.SetSelectedIndex(SUT, 1),
nameof(ItemsRepeaterExtensions.SelectedIndexesProperty) => () => ItemsRepeaterExtensions.SetSelectedIndexes(SUT, new int[] { 1 }),

_ => default(Action) ?? throw new ArgumentOutOfRangeException(property),
})();
Assert.AreEqual(true, IsChipSelectedAt(SUT, 1));
}
}
10 changes: 8 additions & 2 deletions src/Uno.Toolkit.UI/Behaviors/ItemsRepeaterExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -239,12 +239,18 @@ private static void OnSelectionStateChanged(DependencyObject sender, DependencyP
if (ir.ItemsSourceView is { Count: > 0 })
{
var indexes = MapStateToIndexes();
if (indexes.All(x => 0 <= x && x < ir.ItemsSourceView.Count))

// validate indexes are within bounds
var count = ir.ItemsSourceView.Count;
if (indexes.All(x => 0 <= x && x < count))
{
// commit selection change
SetSelectionStates(ir, indexes);
SynchronizeMaterializedElementsSelection(ir);
}
else
{
// rollback
ir.SetValue(e.Property, e.OldValue);
}
}
Expand All @@ -264,7 +270,7 @@ int[] MapStateToIndexes()
{
if (e.NewValue == null) return Array.Empty<int>();

var selectedItems = e.Property == SelectedItemsProperty
var selectedItems = e.Property == SelectedItemProperty
? new[] { e.NewValue }
: (IList<object>)e.NewValue;

Expand Down

0 comments on commit e38ebad

Please sign in to comment.