// Copyright (c) The Perspex Project. All rights reserved. // Licensed under the MIT license. See licence.md file in the project root for full license information. using System.Collections.ObjectModel; using System.Linq; using Moq; using Perspex.Collections; using Perspex.Controls.Generators; using Perspex.Controls.Presenters; using Perspex.Controls.Templates; using Perspex.Input; using Perspex.VisualTree; using Xunit; namespace Perspex.Controls.UnitTests.Presenters { public class ItemsPresenterTests { [Fact] public void Should_Register_With_Host_When_TemplatedParent_Set() { var host = new Mock(); var target = new ItemsPresenter(); target.SetValue(Control.TemplatedParentProperty, host.Object); host.Verify(x => x.RegisterItemsPresenter(target)); } [Fact] public void Should_Add_Containers() { var target = new ItemsPresenter { Items = new[] { "foo", "bar" }, }; target.ApplyTemplate(); Assert.Equal(2, target.Panel.Children.Count); Assert.IsType(target.Panel.Children[0]); Assert.IsType(target.Panel.Children[1]); Assert.Equal("foo", ((TextBlock)target.Panel.Children[0]).Text); Assert.Equal("bar", ((TextBlock)target.Panel.Children[1]).Text); } [Fact] public void Should_Add_Containers_Of_Correct_Type() { var target = new ItemsPresenter { Items = new[] { "foo", "bar" }, }; target.ItemContainerGenerator = new ItemContainerGenerator( target, ListBoxItem.ContentProperty); target.ApplyTemplate(); Assert.Equal(2, target.Panel.Children.Count); Assert.IsType(target.Panel.Children[0]); Assert.IsType(target.Panel.Children[1]); } [Fact] public void ItemContainerGenerator_Should_Be_Picked_Up_From_TemplatedControl() { var parent = new TestItemsControl(); var target = new ItemsPresenter { TemplatedParent = parent, }; Assert.IsType>(target.ItemContainerGenerator); } [Fact] public void Should_Remove_Containers() { var items = new PerspexList(new[] { "foo", "bar" }); var target = new ItemsPresenter { Items = items, }; target.ApplyTemplate(); items.RemoveAt(0); Assert.Equal(1, target.Panel.Children.Count); Assert.Equal("bar", ((TextBlock)target.Panel.Children[0]).Text); Assert.Equal("bar", ((TextBlock)target.ItemContainerGenerator.ContainerFromIndex(0)).Text); } [Fact] public void Clearing_Items_Should_Remove_Containers() { var items = new ObservableCollection { "foo", "bar" }; var target = new ItemsPresenter { Items = items, }; target.ApplyTemplate(); items.Clear(); Assert.Empty(target.Panel.Children); Assert.Empty(target.ItemContainerGenerator.Containers); } [Fact] public void Replacing_Items_Should_Update_Containers() { var items = new ObservableCollection { "foo", "bar", "baz" }; var target = new ItemsPresenter { Items = items, }; target.ApplyTemplate(); items[1] = "baz"; var text = target.Panel.Children .OfType() .Select(x => x.Text) .ToList(); Assert.Equal(new[] { "foo", "baz", "baz" }, text); } [Fact] public void Moving_Items_Should_Update_Containers() { var items = new ObservableCollection { "foo", "bar", "baz" }; var target = new ItemsPresenter { Items = items, }; target.ApplyTemplate(); items.Move(2, 1); var text = target.Panel.Children .OfType() .Select(x => x.Text) .ToList(); Assert.Equal(new[] { "foo", "baz", "bar" }, text); } [Fact] public void Inserting_Items_Should_Update_Containers() { var items = new ObservableCollection { "foo", "bar", "baz" }; var target = new ItemsPresenter { Items = items, }; target.ApplyTemplate(); items.Insert(2, "insert"); var text = target.Panel.Children .OfType() .Select(x => x.Text) .ToList(); Assert.Equal(new[] { "foo", "bar", "insert", "baz" }, text); } [Fact] public void Setting_Items_To_Null_Should_Remove_Containers() { var target = new ItemsPresenter { Items = new[] { "foo", "bar" }, }; target.ApplyTemplate(); target.Items = null; Assert.Empty(target.Panel.Children); Assert.Empty(target.ItemContainerGenerator.Containers); } [Fact] public void Should_Handle_Null_Items() { var items = new PerspexList(new[] { "foo", null, "bar" }); var target = new ItemsPresenter { Items = items, }; target.ApplyTemplate(); var text = target.Panel.Children.Cast().Select(x => x.Text).ToList(); Assert.Equal(new[] { "foo", "bar" }, text); Assert.NotNull(target.ItemContainerGenerator.ContainerFromIndex(0)); Assert.Null(target.ItemContainerGenerator.ContainerFromIndex(1)); Assert.NotNull(target.ItemContainerGenerator.ContainerFromIndex(2)); items.RemoveAt(1); text = target.Panel.Children.Cast().Select(x => x.Text).ToList(); Assert.Equal(new[] { "foo", "bar" }, text); Assert.NotNull(target.ItemContainerGenerator.ContainerFromIndex(0)); Assert.NotNull(target.ItemContainerGenerator.ContainerFromIndex(1)); } [Fact] public void Should_Handle_Duplicate_Items() { var items = new PerspexList(new[] { 1, 2, 1 }); var target = new ItemsPresenter { Items = items, }; target.ApplyTemplate(); items.RemoveAt(2); var text = target.Panel.Children.OfType().Select(x => x.Text); Assert.Equal(new[] { "1", "2" }, text); } [Fact] public void Panel_Should_Be_Created_From_ItemsPanel_Template() { var panel = new Panel(); var target = new ItemsPresenter { ItemsPanel = new FuncTemplate(() => panel), }; target.ApplyTemplate(); Assert.Same(panel, target.Panel); Assert.Same(target, target.Panel.Parent); } [Fact] public void Panel_TabNavigation_Should_Be_Set_To_Once() { var target = new ItemsPresenter(); target.ApplyTemplate(); Assert.Equal(KeyboardNavigationMode.Once, KeyboardNavigation.GetTabNavigation((InputElement)target.Panel)); } [Fact] public void Panel_TabNavigation_Should_Be_Set_To_ItemsPresenter_Value() { var target = new ItemsPresenter(); KeyboardNavigation.SetTabNavigation(target, KeyboardNavigationMode.Cycle); target.ApplyTemplate(); Assert.Equal(KeyboardNavigationMode.Cycle, KeyboardNavigation.GetTabNavigation((InputElement)target.Panel)); } [Fact] public void Panel_Should_Be_Visual_Child() { var target = new ItemsPresenter(); target.ApplyTemplate(); var child = target.GetVisualChildren().Single(); Assert.Equal(target.Panel, child); } [Fact] public void MemberSelector_Should_Select_Member() { var target = new ItemsPresenter { Items = new[] { new Item("Foo"), new Item("Bar") }, MemberSelector = new FuncMemberSelector(x => x.Value), }; target.ApplyTemplate(); var text = target.Panel.Children .Cast() .Select(x => x.Text) .ToList(); Assert.Equal(new[] { "Foo", "Bar" }, text); } [Fact] public void MemberSelector_Should_Set_DataContext() { var items = new[] { new Item("Foo"), new Item("Bar") }; var target = new ItemsPresenter { Items = items, MemberSelector = new FuncMemberSelector(x => x.Value), }; target.ApplyTemplate(); var dataContexts = target.Panel.Children .Cast() .Select(x => x.DataContext) .ToList(); Assert.Equal(new[] { "Foo", "Bar" }, dataContexts); } private class Item { public Item(string value) { Value = value; } public string Value { get; } } private class TestItem : ContentControl { } private class TestItemsControl : ItemsControl { protected override IItemContainerGenerator CreateItemContainerGenerator() { return new ItemContainerGenerator(this, TestItem.ContentProperty); } } } }