Skip to content

Commit

Permalink
Merge pull request #5844 from VisualMelon/ItemsControlItemCount
Browse files Browse the repository at this point in the history
Use ItemCount to determine PseudoClass in ItemsControl for better consistency
  • Loading branch information
grokys authored and Dan Walmsley committed Apr 30, 2021
1 parent a37ccee commit 9338571
Show file tree
Hide file tree
Showing 2 changed files with 140 additions and 8 deletions.
25 changes: 17 additions & 8 deletions src/Avalonia.Controls/ItemsControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ static ItemsControl()
/// </summary>
public ItemsControl()
{
PseudoClasses.Add(":empty");
UpdatePseudoClasses(0);
SubscribeToItems(_items);
}

Expand Down Expand Up @@ -323,6 +323,16 @@ protected override void OnKeyDown(KeyEventArgs e)
base.OnKeyDown(e);
}

protected override void OnPropertyChanged<T>(AvaloniaPropertyChangedEventArgs<T> change)
{
base.OnPropertyChanged(change);

if (change.Property == ItemCountProperty)
{
UpdatePseudoClasses(change.NewValue.GetValueOrDefault<int>());
}
}

/// <summary>
/// Called when the <see cref="Items"/> property changes.
/// </summary>
Expand Down Expand Up @@ -371,10 +381,6 @@ protected virtual void ItemsCollectionChanged(object sender, NotifyCollectionCha
}

Presenter?.ItemsChanged(e);

var collection = sender as ICollection;
PseudoClasses.Set(":empty", collection == null || collection.Count == 0);
PseudoClasses.Set(":singleitem", collection != null && collection.Count == 1);
}

/// <summary>
Expand Down Expand Up @@ -431,9 +437,6 @@ private void RemoveControlItemsFromLogicalChildren(IEnumerable items)
/// <param name="items">The items collection.</param>
private void SubscribeToItems(IEnumerable items)
{
PseudoClasses.Set(":empty", items == null || items.Count() == 0);
PseudoClasses.Set(":singleitem", items != null && items.Count() == 1);

if (items is INotifyCollectionChanged incc)
{
CollectionChangedEventManager.Instance.AddListener(incc, this);
Expand Down Expand Up @@ -469,6 +472,12 @@ private void UpdateItemCount()
}
}

private void UpdatePseudoClasses(int itemCount)
{
PseudoClasses.Set(":empty", itemCount == 0);
PseudoClasses.Set(":singleitem", itemCount == 1);
}

protected static IInputElement GetNextControl(
INavigableContainer container,
NavigationDirection direction,
Expand Down
123 changes: 123 additions & 0 deletions tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,17 @@ public void Empty_Class_Should_Be_Cleared_When_Items_Added()
Assert.DoesNotContain(":empty", target.Classes);
}

[Fact]
public void Empty_Class_Should_Be_Set_When_Items_Not_Set()
{
var target = new ItemsControl()
{
Template = GetTemplate(),
};

Assert.Contains(":empty", target.Classes);
}

[Fact]
public void Empty_Class_Should_Be_Set_When_Empty_Collection_Set()
{
Expand All @@ -393,6 +404,118 @@ public void Empty_Class_Should_Be_Set_When_Empty_Collection_Set()
Assert.Contains(":empty", target.Classes);
}

[Fact]
public void Item_Count_Should_Be_Set_When_Items_Added()
{
var target = new ItemsControl()
{
Template = GetTemplate(),
Items = new[] { 1, 2, 3 },
};

Assert.Equal(3, target.ItemCount);
}

[Fact]
public void Item_Count_Should_Be_Set_When_Items_Changed()
{
var items = new ObservableCollection<int>() { 1, 2, 3 };

var target = new ItemsControl()
{
Template = GetTemplate(),
Items = items,
};

items.Add(4);

Assert.Equal(4, target.ItemCount);

items.Clear();

Assert.Equal(0, target.ItemCount);
}

[Fact]
public void Empty_Class_Should_Be_Set_When_Items_Collection_Cleared()
{
var items = new ObservableCollection<int>() { 1, 2, 3 };

var target = new ItemsControl()
{
Template = GetTemplate(),
Items = items,
};

items.Clear();

Assert.Contains(":empty", target.Classes);
}

[Fact]
public void Empty_Class_Should_Not_Be_Set_When_Items_Collection_Count_Increases()
{
var items = new ObservableCollection<int>() { };

var target = new ItemsControl()
{
Template = GetTemplate(),
Items = items,
};

items.Add(1);

Assert.DoesNotContain(":empty", target.Classes);
}

[Fact]
public void Single_Item_Class_Should_Be_Set_When_Items_Collection_Count_Increases_To_One()
{
var items = new ObservableCollection<int>() { };

var target = new ItemsControl()
{
Template = GetTemplate(),
Items = items,
};

items.Add(1);

Assert.Contains(":singleitem", target.Classes);
}

[Fact]
public void Empty_Class_Should_Not_Be_Set_When_Items_Collection_Cleared()
{
var items = new ObservableCollection<int>() { 1, 2, 3 };

var target = new ItemsControl()
{
Template = GetTemplate(),
Items = items,
};

items.Clear();

Assert.DoesNotContain(":singleitem", target.Classes);
}

[Fact]
public void Single_Item_Class_Should_Not_Be_Set_When_Items_Collection_Count_Increases_Beyond_One()
{
var items = new ObservableCollection<int>() { 1 };

var target = new ItemsControl()
{
Template = GetTemplate(),
Items = items,
};

items.Add(2);

Assert.DoesNotContain(":singleitem", target.Classes);
}

[Fact]
public void Setting_Presenter_Explicitly_Should_Set_Item_Parent()
{
Expand Down

0 comments on commit 9338571

Please sign in to comment.