Browse Source

Merge pull request #799 from VitalElement/fixes/failing-unit-test

Fixes for Carousel Logical Tree
pull/801/head
danwalmsley 10 years ago
committed by GitHub
parent
commit
ef3a90df0d
  1. 5
      src/Avalonia.Controls/Generators/IItemContainerGenerator.cs
  2. 3
      src/Avalonia.Controls/Generators/ItemContainerGenerator.cs
  3. 3
      src/Avalonia.Controls/Generators/ItemContainerGenerator`1.cs
  4. 50
      src/Avalonia.Controls/ItemsControl.cs
  5. 5
      tests/Avalonia.Controls.UnitTests/CarouselTests.cs
  6. 33
      tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs

5
src/Avalonia.Controls/Generators/IItemContainerGenerator.cs

@ -22,6 +22,11 @@ namespace Avalonia.Controls.Generators
/// </summary> /// </summary>
IDataTemplate ItemTemplate { get; set; } IDataTemplate ItemTemplate { get; set; }
/// <summary>
/// Gets the ContainerType, or null if its an untyped ContainerGenerator.
/// </summary>
Type ContainerType { get; }
/// <summary> /// <summary>
/// Signalled whenever new containers are materialized. /// Signalled whenever new containers are materialized.
/// </summary> /// </summary>

3
src/Avalonia.Controls/Generators/ItemContainerGenerator.cs

@ -50,6 +50,9 @@ namespace Avalonia.Controls.Generators
/// </summary> /// </summary>
public IControl Owner { get; } public IControl Owner { get; }
/// <inheritdoc/>
public virtual Type ContainerType => null;
/// <inheritdoc/> /// <inheritdoc/>
public ItemContainerInfo Materialize( public ItemContainerInfo Materialize(
int index, int index,

3
src/Avalonia.Controls/Generators/ItemContainerGenerator`1.cs

@ -34,6 +34,9 @@ namespace Avalonia.Controls.Generators
ContentTemplateProperty = contentTemplateProperty; ContentTemplateProperty = contentTemplateProperty;
} }
/// <inheritdoc/>
public override Type ContainerType => typeof(T);
/// <summary> /// <summary>
/// Gets the container's Content property. /// Gets the container's Content property.
/// </summary> /// </summary>

50
src/Avalonia.Controls/ItemsControl.cs

@ -4,7 +4,6 @@
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using Avalonia.Collections; using Avalonia.Collections;
using Avalonia.Controls.Generators; using Avalonia.Controls.Generators;
@ -226,19 +225,35 @@ namespace Avalonia.Controls
/// <param name="e">The details of the containers.</param> /// <param name="e">The details of the containers.</param>
protected virtual void OnContainersMaterialized(ItemContainerEventArgs e) protected virtual void OnContainersMaterialized(ItemContainerEventArgs e)
{ {
var toAdd = new List<ILogical>();
foreach (var container in e.Containers) foreach (var container in e.Containers)
{ {
// If the item is its own container, then it will be added to the logical tree when // If the item is its own container, then it will be added to the logical tree when
// it was added to the Items collection. // it was added to the Items collection.
if (container.ContainerControl != null && container.ContainerControl != container.Item) if (container.ContainerControl != null && container.ContainerControl != container.Item)
{ {
toAdd.Add(container.ContainerControl); if (ItemContainerGenerator.ContainerType == null)
{
var containerControl = container.ContainerControl as ContentPresenter;
if (containerControl != null)
{
((ISetLogicalParent)containerControl).SetParent(this);
containerControl.SetValue(TemplatedParentProperty, null);
containerControl.UpdateChild();
if (containerControl.Child != null)
{
LogicalChildren.Add(containerControl.Child);
}
}
}
else
{
LogicalChildren.Add(container.ContainerControl);
}
} }
} }
LogicalChildren.AddRange(toAdd);
} }
/// <summary> /// <summary>
@ -248,19 +263,32 @@ namespace Avalonia.Controls
/// <param name="e">The details of the containers.</param> /// <param name="e">The details of the containers.</param>
protected virtual void OnContainersDematerialized(ItemContainerEventArgs e) protected virtual void OnContainersDematerialized(ItemContainerEventArgs e)
{ {
var toRemove = new List<ILogical>();
foreach (var container in e.Containers) foreach (var container in e.Containers)
{ {
// If the item is its own container, then it will be removed from the logical tree // If the item is its own container, then it will be removed from the logical tree
// when it is removed from the Items collection. // when it is removed from the Items collection.
if (container?.ContainerControl != container?.Item) if (container?.ContainerControl != container?.Item)
{ {
toRemove.Add(container.ContainerControl); if (ItemContainerGenerator.ContainerType == null)
{
var containerControl = container.ContainerControl as ContentPresenter;
if (containerControl != null)
{
((ISetLogicalParent)containerControl).SetParent(null);
if (containerControl.Child != null)
{
LogicalChildren.Remove(containerControl.Child);
}
}
}
else
{
LogicalChildren.Remove(container.ContainerControl);
}
} }
} }
LogicalChildren.RemoveAll(toRemove);
} }
/// <summary> /// <summary>

5
tests/Avalonia.Controls.UnitTests/CarouselTests.cs

@ -50,8 +50,9 @@ namespace Avalonia.Controls.UnitTests
Assert.Equal(1, target.GetLogicalChildren().Count()); Assert.Equal(1, target.GetLogicalChildren().Count());
var child = target.GetLogicalChildren().Single(); var child = target.GetLogicalChildren().Single();
Assert.IsType<ContentPresenter>(child);
Assert.Equal("Foo", ((ContentPresenter)child).Content); Assert.IsType<TextBlock>(child);
Assert.Equal("Foo", ((TextBlock)child).Text);
} }
[Fact] [Fact]

33
tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs

@ -9,6 +9,8 @@ using Avalonia.Controls.Templates;
using Avalonia.LogicalTree; using Avalonia.LogicalTree;
using Avalonia.VisualTree; using Avalonia.VisualTree;
using Xunit; using Xunit;
using System.Collections.ObjectModel;
using Avalonia.UnitTests;
namespace Avalonia.Controls.UnitTests namespace Avalonia.Controls.UnitTests
{ {
@ -61,6 +63,32 @@ namespace Avalonia.Controls.UnitTests
Assert.Null(container.TemplatedParent); Assert.Null(container.TemplatedParent);
} }
[Fact]
public void Container_Child_Should_Have_LogicalParent_Set_To_Container()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var root = new Window();
var target = new ItemsControl();
root.Content = target;
var templatedParent = new Button();
target.TemplatedParent = templatedParent;
target.Template = GetTemplate();
target.Items = new[] { "Foo" };
root.ApplyTemplate();
target.ApplyTemplate();
target.Presenter.ApplyTemplate();
var container = (ContentPresenter)target.Presenter.Panel.Children[0];
Assert.Equal(container, container.Child.Parent);
}
}
[Fact] [Fact]
public void Control_Item_Should_Be_Logical_Child_Before_ApplyTemplate() public void Control_Item_Should_Be_Logical_Child_Before_ApplyTemplate()
{ {
@ -138,7 +166,7 @@ namespace Avalonia.Controls.UnitTests
} }
[Fact] [Fact]
public void Adding_String_Item_Should_Make_ContentPresenter_Appear_In_LogicalChildren() public void Adding_String_Item_Should_Make_TextBlock_Appear_In_LogicalChildren()
{ {
var target = new ItemsControl(); var target = new ItemsControl();
var child = new Control(); var child = new Control();
@ -150,7 +178,7 @@ namespace Avalonia.Controls.UnitTests
var logical = (ILogical)target; var logical = (ILogical)target;
Assert.Equal(1, logical.LogicalChildren.Count); Assert.Equal(1, logical.LogicalChildren.Count);
Assert.IsType<ContentPresenter>(logical.LogicalChildren[0]); Assert.IsType<TextBlock>(logical.LogicalChildren[0]);
} }
[Fact] [Fact]
@ -171,6 +199,7 @@ namespace Avalonia.Controls.UnitTests
Assert.Equal(new ILogical[0], target.GetLogicalChildren()); Assert.Equal(new ILogical[0], target.GetLogicalChildren());
} }
[Fact] [Fact]
public void Setting_Items_Should_Fire_LogicalChildren_CollectionChanged() public void Setting_Items_Should_Fire_LogicalChildren_CollectionChanged()
{ {

Loading…
Cancel
Save