Merge pull request #456 from irihitech/issue-455
Fix breadcrumb indexing when insertion from itemssource.
This commit is contained in:
@@ -5,6 +5,7 @@ using Avalonia.Controls.Templates;
|
|||||||
using Avalonia.Data;
|
using Avalonia.Data;
|
||||||
using Avalonia.Layout;
|
using Avalonia.Layout;
|
||||||
using Avalonia.Metadata;
|
using Avalonia.Metadata;
|
||||||
|
using Avalonia.VisualTree;
|
||||||
|
|
||||||
namespace Ursa.Controls;
|
namespace Ursa.Controls;
|
||||||
|
|
||||||
@@ -84,17 +85,6 @@ public class Breadcrumb: ItemsControl
|
|||||||
return new BreadcrumbItem();
|
return new BreadcrumbItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LogicalChildrenCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
|
|
||||||
{
|
|
||||||
base.LogicalChildrenCollectionChanged(sender, e);
|
|
||||||
var breadcrumbItems = LogicalChildren.OfType<BreadcrumbItem>().ToList();
|
|
||||||
for (var i = 0; i < breadcrumbItems.Count; i++)
|
|
||||||
{
|
|
||||||
var breadcrumbItem = breadcrumbItems[i];
|
|
||||||
breadcrumbItem.SetPseudoClassLast(i == breadcrumbItems.Count - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void PrepareContainerForItemOverride(Control container, object? item, int index)
|
protected override void PrepareContainerForItemOverride(Control container, object? item, int index)
|
||||||
{
|
{
|
||||||
if (container is not BreadcrumbItem breadcrumbItem) return;
|
if (container is not BreadcrumbItem breadcrumbItem) return;
|
||||||
@@ -149,4 +139,13 @@ public class Breadcrumb: ItemsControl
|
|||||||
ITemplate<Control?> t => t.Build(),
|
ITemplate<Control?> t => t.Build(),
|
||||||
_ => separator.ToString()
|
_ => separator.ToString()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
internal void InvalidateContainers()
|
||||||
|
{
|
||||||
|
var breadcrumbItems = this.GetVisualDescendants().OfType<BreadcrumbItem>().ToList();
|
||||||
|
for (var i = 0; i < breadcrumbItems.Count; i++)
|
||||||
|
{
|
||||||
|
breadcrumbItems[i].SetPseudoClassLast(i == breadcrumbItems.Count - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -79,4 +79,11 @@ public class BreadcrumbItem: ContentControl
|
|||||||
{
|
{
|
||||||
PseudoClasses.Set(PC_Last, isLast);
|
PseudoClasses.Set(PC_Last, isLast);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnAttachedToVisualTree(e);
|
||||||
|
var parent = this.Parent as Breadcrumb;
|
||||||
|
parent?.InvalidateContainers();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@ using System.Collections.ObjectModel;
|
|||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Headless.XUnit;
|
using Avalonia.Headless.XUnit;
|
||||||
using Avalonia.LogicalTree;
|
using Avalonia.LogicalTree;
|
||||||
|
using Avalonia.VisualTree;
|
||||||
using Ursa.Controls;
|
using Ursa.Controls;
|
||||||
|
|
||||||
namespace HeadlessTest.Ursa.Controls;
|
namespace HeadlessTest.Ursa.Controls;
|
||||||
@@ -24,6 +25,22 @@ public class BreadcrumbTests
|
|||||||
Assert.DoesNotContain(":last", item1.Classes);
|
Assert.DoesNotContain(":last", item1.Classes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[AvaloniaFact]
|
||||||
|
public void BreadcrumbItem_Should_Have_Correct_PseudoClasses_When_Insert()
|
||||||
|
{
|
||||||
|
var window = new Window();
|
||||||
|
var breadcrumb = new Breadcrumb();
|
||||||
|
window.Content = breadcrumb;
|
||||||
|
window.Show();
|
||||||
|
var item1 = new BreadcrumbItem();
|
||||||
|
var item2 = new BreadcrumbItem();
|
||||||
|
breadcrumb.Items.Add(item1);
|
||||||
|
Assert.Contains(":last", item1.Classes);
|
||||||
|
breadcrumb.Items.Insert(0, item2);
|
||||||
|
Assert.Contains(":last", item1.Classes);
|
||||||
|
Assert.DoesNotContain(":last", item2.Classes);
|
||||||
|
}
|
||||||
|
|
||||||
[AvaloniaFact]
|
[AvaloniaFact]
|
||||||
public void Generated_BreadcrumbItem_Should_Have_Correct_PseudoClasses()
|
public void Generated_BreadcrumbItem_Should_Have_Correct_PseudoClasses()
|
||||||
{
|
{
|
||||||
@@ -34,16 +51,38 @@ public class BreadcrumbTests
|
|||||||
var item1 = new TextBlock();
|
var item1 = new TextBlock();
|
||||||
var item2 = new TextBlock();
|
var item2 = new TextBlock();
|
||||||
breadcrumb.Items.Add(item1);
|
breadcrumb.Items.Add(item1);
|
||||||
var firstItem = breadcrumb.GetLogicalChildren().OfType<BreadcrumbItem>().FirstOrDefault();
|
var firstItem = breadcrumb.GetVisualDescendants().OfType<BreadcrumbItem>().FirstOrDefault();
|
||||||
Assert.NotNull(firstItem);
|
Assert.NotNull(firstItem);
|
||||||
Assert.Contains(":last", firstItem.Classes);
|
Assert.Contains(":last", firstItem.Classes);
|
||||||
breadcrumb.Items.Add(item2);
|
breadcrumb.Items.Add(item2);
|
||||||
var lastItem = breadcrumb.GetLogicalChildren().OfType<BreadcrumbItem>().LastOrDefault();
|
var lastItem = breadcrumb.GetVisualDescendants().OfType<BreadcrumbItem>().LastOrDefault();
|
||||||
Assert.NotNull(lastItem);
|
Assert.NotNull(lastItem);
|
||||||
Assert.Contains(":last", lastItem.Classes);
|
Assert.Contains(":last", lastItem.Classes);
|
||||||
Assert.DoesNotContain(":last", firstItem.Classes);
|
Assert.DoesNotContain(":last", firstItem.Classes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[AvaloniaFact]
|
||||||
|
public void Generated_BreadcrumbItem_Should_Have_Correct_PseudoClasses_When_Insert()
|
||||||
|
{
|
||||||
|
var window = new Window();
|
||||||
|
var breadcrumb = new Breadcrumb();
|
||||||
|
window.Content = breadcrumb;
|
||||||
|
window.Show();
|
||||||
|
var item1 = new TextBlock();
|
||||||
|
var item2 = new TextBlock();
|
||||||
|
breadcrumb.Items.Add(item1);
|
||||||
|
var firstItem = breadcrumb.GetVisualDescendants().OfType<BreadcrumbItem>().FirstOrDefault();
|
||||||
|
Assert.NotNull(firstItem);
|
||||||
|
Assert.Contains(":last", firstItem.Classes);
|
||||||
|
breadcrumb.Items.Insert(0, item2);
|
||||||
|
var lastItem = breadcrumb.GetVisualDescendants().OfType<BreadcrumbItem>().LastOrDefault();
|
||||||
|
Assert.NotNull(lastItem);
|
||||||
|
Assert.Contains(":last", lastItem.Classes);
|
||||||
|
firstItem = breadcrumb.GetVisualDescendants().OfType<BreadcrumbItem>().FirstOrDefault();
|
||||||
|
Assert.NotNull(firstItem);
|
||||||
|
Assert.DoesNotContain(":last", firstItem.Classes);
|
||||||
|
}
|
||||||
|
|
||||||
[AvaloniaFact]
|
[AvaloniaFact]
|
||||||
public void BreadcrumbItem_FromItemsSource_Should_Have_Correct_PseudoClasses()
|
public void BreadcrumbItem_FromItemsSource_Should_Have_Correct_PseudoClasses()
|
||||||
{
|
{
|
||||||
@@ -54,16 +93,38 @@ public class BreadcrumbTests
|
|||||||
var items = new ObservableCollection<string>();
|
var items = new ObservableCollection<string>();
|
||||||
breadcrumb.ItemsSource = items;
|
breadcrumb.ItemsSource = items;
|
||||||
items.Add("Item 1");
|
items.Add("Item 1");
|
||||||
var item1 = breadcrumb.GetLogicalChildren().OfType<BreadcrumbItem>().FirstOrDefault();
|
var item1 = breadcrumb.GetVisualDescendants().OfType<BreadcrumbItem>().FirstOrDefault();
|
||||||
Assert.NotNull(item1);
|
Assert.NotNull(item1);
|
||||||
Assert.Contains(":last", item1.Classes);
|
Assert.Contains(":last", item1.Classes);
|
||||||
items.Add("Item 2");
|
items.Add("Item 2");
|
||||||
var item2 = breadcrumb.GetLogicalChildren().OfType<BreadcrumbItem>().LastOrDefault();
|
var item2 = breadcrumb.GetVisualDescendants().OfType<BreadcrumbItem>().LastOrDefault();
|
||||||
Assert.NotNull(item2);
|
Assert.NotNull(item2);
|
||||||
Assert.Contains(":last", item2.Classes);
|
Assert.Contains(":last", item2.Classes);
|
||||||
Assert.DoesNotContain(":last", item1.Classes);
|
Assert.DoesNotContain(":last", item1.Classes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[AvaloniaFact]
|
||||||
|
public void BreadcrumbItem_FromItemsSource_Should_Have_Correct_PseudoClasses_When_Insert()
|
||||||
|
{
|
||||||
|
var window = new Window();
|
||||||
|
var breadcrumb = new Breadcrumb();
|
||||||
|
window.Content = breadcrumb;
|
||||||
|
window.Show();
|
||||||
|
var items = new ObservableCollection<string>();
|
||||||
|
breadcrumb.ItemsSource = items;
|
||||||
|
items.Add("Item 1");
|
||||||
|
var item1 = breadcrumb.GetVisualDescendants().OfType<BreadcrumbItem>().FirstOrDefault();
|
||||||
|
Assert.NotNull(item1);
|
||||||
|
Assert.Contains(":last", item1.Classes);
|
||||||
|
items.Insert(0, "Item 2");
|
||||||
|
var item2 = breadcrumb.GetVisualDescendants().OfType<BreadcrumbItem>().LastOrDefault();
|
||||||
|
Assert.NotNull(item2);
|
||||||
|
Assert.Contains(":last", item2.Classes);
|
||||||
|
var newItem1 = breadcrumb.GetVisualDescendants().OfType<BreadcrumbItem>().FirstOrDefault();
|
||||||
|
Assert.NotNull(newItem1);
|
||||||
|
Assert.DoesNotContain(":last", newItem1.Classes);
|
||||||
|
}
|
||||||
|
|
||||||
[AvaloniaFact]
|
[AvaloniaFact]
|
||||||
public void Bulk_Added_BreadcrumbItem_Should_Have_Correct_PseudoClasses()
|
public void Bulk_Added_BreadcrumbItem_Should_Have_Correct_PseudoClasses()
|
||||||
{
|
{
|
||||||
@@ -77,8 +138,8 @@ public class BreadcrumbTests
|
|||||||
"Item 2"
|
"Item 2"
|
||||||
};
|
};
|
||||||
breadcrumb.ItemsSource = items;
|
breadcrumb.ItemsSource = items;
|
||||||
var item1 = breadcrumb.GetLogicalChildren().OfType<BreadcrumbItem>().FirstOrDefault();
|
var item1 = breadcrumb.GetVisualDescendants().OfType<BreadcrumbItem>().FirstOrDefault();
|
||||||
var item2 = breadcrumb.GetLogicalChildren().OfType<BreadcrumbItem>().LastOrDefault();
|
var item2 = breadcrumb.GetVisualDescendants().OfType<BreadcrumbItem>().LastOrDefault();
|
||||||
Assert.NotNull(item1);
|
Assert.NotNull(item1);
|
||||||
Assert.NotNull(item2);
|
Assert.NotNull(item2);
|
||||||
Assert.Contains(":last", item2.Classes);
|
Assert.Contains(":last", item2.Classes);
|
||||||
|
|||||||
Reference in New Issue
Block a user