Browse Source

Make ItemContainerGenerator create containers

Make the untyped ItemContainerGenerator create `ContentPresenter`
containers when the data isn't a control. This is required for correct
binding to `DataContext` in a data template.
pull/558/head
Steven Kirk 10 years ago
parent
commit
fbb7ea759b
  1. 14
      src/Avalonia.Controls/Generators/ItemContainerGenerator.cs
  2. 1
      tests/Avalonia.Controls.UnitTests/Avalonia.Controls.UnitTests.csproj
  3. 4
      tests/Avalonia.Controls.UnitTests/CarouselTests.cs
  4. 5
      tests/Avalonia.Controls.UnitTests/Generators/ItemContainerGeneratorTests.cs
  5. 27
      tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs
  6. 8
      tests/Avalonia.Controls.UnitTests/Presenters/CarouselPresenterTests.cs
  7. 45
      tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests.cs
  8. 16
      tests/Avalonia.Controls.UnitTests/TabControlTests.cs

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

@ -2,12 +2,10 @@
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Subjects;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Templates;
using Avalonia.Controls.Utils;
namespace Avalonia.Controls.Generators
{
@ -185,11 +183,15 @@ namespace Avalonia.Controls.Generators
/// <returns>The created container control.</returns>
protected virtual IControl CreateContainer(object item)
{
var result = Owner.MaterializeDataTemplate(item, ItemTemplate);
var result = item as IControl;
if (result != null && !(item is IControl))
if (result == null)
{
result.DataContext = item;
result = new ContentPresenter
{
ContentTemplate = ItemTemplate,
Content = item,
};
}
return result;

1
tests/Avalonia.Controls.UnitTests/Avalonia.Controls.UnitTests.csproj

@ -102,7 +102,6 @@
<Compile Include="HeaderedItemsControlTests .cs" />
<Compile Include="ControlTests_NameScope.cs" />
<Compile Include="Generators\ItemContainerGeneratorTests.cs" />
<Compile Include="Generators\ItemContainerGeneratorTypedTests.cs" />
<Compile Include="GridLengthTests.cs" />
<Compile Include="ImageTests.cs" />
<Compile Include="Presenters\ContentPresenterTests.cs" />

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

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

5
tests/Avalonia.Controls.UnitTests/Generators/ItemContainerGeneratorTests.cs

@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Linq;
using Avalonia.Controls.Generators;
using Avalonia.Controls.Presenters;
using Xunit;
namespace Avalonia.Controls.UnitTests.Generators
@ -19,8 +20,8 @@ namespace Avalonia.Controls.UnitTests.Generators
var containers = Materialize(target, 0, items);
var result = containers
.Select(x => x.ContainerControl)
.OfType<TextBlock>()
.Select(x => x.Text)
.OfType<ContentPresenter>()
.Select(x => x.Content)
.ToList();
Assert.Equal(items, result);

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

@ -27,7 +27,10 @@ namespace Avalonia.Controls.UnitTests
target.ApplyTemplate();
target.Presenter.ApplyTemplate();
Assert.IsType<Canvas>(target.Presenter.Panel.Children[0]);
var container = (ContentPresenter)target.Presenter.Panel.Children[0];
container.UpdateChild();
Assert.IsType<Canvas>(container.Child);
}
[Fact]
@ -44,7 +47,7 @@ namespace Avalonia.Controls.UnitTests
}
[Fact]
public void Item_Should_Have_TemplatedParent_Set_To_Null()
public void Container_Should_Have_TemplatedParent_Set_To_Null()
{
var target = new ItemsControl();
@ -53,9 +56,9 @@ namespace Avalonia.Controls.UnitTests
target.ApplyTemplate();
target.Presenter.ApplyTemplate();
var item = (TextBlock)target.Presenter.Panel.GetVisualChildren().First();
var container = (ContentPresenter)target.Presenter.Panel.Children[0];
Assert.Null(item.TemplatedParent);
Assert.Null(container.TemplatedParent);
}
[Fact]
@ -135,7 +138,7 @@ namespace Avalonia.Controls.UnitTests
}
[Fact]
public void Adding_String_Item_Should_Make_TextBlock_Appear_In_LogicalChildren()
public void Adding_String_Item_Should_Make_ContentPresenter_Appear_In_LogicalChildren()
{
var target = new ItemsControl();
var child = new Control();
@ -147,7 +150,7 @@ namespace Avalonia.Controls.UnitTests
var logical = (ILogical)target;
Assert.Equal(1, logical.LogicalChildren.Count);
Assert.IsType<TextBlock>(logical.LogicalChildren[0]);
Assert.IsType<ContentPresenter>(logical.LogicalChildren[0]);
}
[Fact]
@ -390,8 +393,8 @@ namespace Avalonia.Controls.UnitTests
target.Presenter.ApplyTemplate();
var text = target.Presenter.Panel.Children
.Cast<TextBlock>()
.Select(x => x.Text)
.Cast<ContentPresenter>()
.Select(x => x.Content)
.ToList();
Assert.Equal(new[] { "Foo", "Bar" }, text);
@ -419,7 +422,7 @@ namespace Avalonia.Controls.UnitTests
}
[Fact]
public void DataTemplate_Created_Item_Should_Be_NameScope()
public void DataTemplate_Created_Content_Should_Be_NameScope()
{
var items = new object[]
{
@ -435,8 +438,10 @@ namespace Avalonia.Controls.UnitTests
target.ApplyTemplate();
target.Presenter.ApplyTemplate();
var item = target.Presenter.Panel.LogicalChildren[0];
Assert.NotNull(NameScope.GetNameScope((TextBlock)item));
var container = (ContentPresenter)target.Presenter.Panel.LogicalChildren[0];
container.UpdateChild();
Assert.NotNull(NameScope.GetNameScope((TextBlock)container.Child));
}
private class Item

8
tests/Avalonia.Controls.UnitTests/Presenters/CarouselPresenterTests.cs

@ -60,8 +60,8 @@ namespace Avalonia.Controls.UnitTests.Presenters
target.ApplyTemplate();
Assert.IsType<TextBlock>(target.Panel.Children[0]);
Assert.Equal("foo", ((TextBlock)target.Panel.Children[0]).Text);
Assert.IsType<ContentPresenter>(target.Panel.Children[0]);
Assert.Equal("foo", ((ContentPresenter)target.Panel.Children[0]).Content);
}
[Fact]
@ -76,8 +76,8 @@ namespace Avalonia.Controls.UnitTests.Presenters
target.ApplyTemplate();
target.SelectedIndex = 1;
Assert.IsType<TextBlock>(target.Panel.Children[0]);
Assert.Equal("bar", ((TextBlock)target.Panel.Children[0]).Text);
Assert.IsType<ContentPresenter>(target.Panel.Children[0]);
Assert.Equal("bar", ((ContentPresenter)target.Panel.Children[0]).Content);
}
[Fact]

45
tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests.cs

@ -38,10 +38,10 @@ namespace Avalonia.Controls.UnitTests.Presenters
target.ApplyTemplate();
Assert.Equal(2, target.Panel.Children.Count);
Assert.IsType<TextBlock>(target.Panel.Children[0]);
Assert.IsType<TextBlock>(target.Panel.Children[1]);
Assert.Equal("foo", ((TextBlock)target.Panel.Children[0]).Text);
Assert.Equal("bar", ((TextBlock)target.Panel.Children[1]).Text);
Assert.IsType<ContentPresenter>(target.Panel.Children[0]);
Assert.IsType<ContentPresenter>(target.Panel.Children[1]);
Assert.Equal("foo", ((ContentPresenter)target.Panel.Children[0]).Content);
Assert.Equal("bar", ((ContentPresenter)target.Panel.Children[1]).Content);
}
[Fact]
@ -88,8 +88,8 @@ namespace Avalonia.Controls.UnitTests.Presenters
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);
Assert.Equal("bar", ((ContentPresenter)target.Panel.Children[0]).Content);
Assert.Equal("bar", ((ContentPresenter)target.ItemContainerGenerator.ContainerFromIndex(0)).Content);
}
[Fact]
@ -121,8 +121,8 @@ namespace Avalonia.Controls.UnitTests.Presenters
items[1] = "baz";
var text = target.Panel.Children
.OfType<TextBlock>()
.Select(x => x.Text)
.OfType<ContentPresenter>()
.Select(x => x.Content)
.ToList();
Assert.Equal(new[] { "foo", "baz", "baz" }, text);
@ -141,8 +141,8 @@ namespace Avalonia.Controls.UnitTests.Presenters
items.Move(2, 1);
var text = target.Panel.Children
.OfType<TextBlock>()
.Select(x => x.Text)
.OfType<ContentPresenter>()
.Select(x => x.Content)
.ToList();
Assert.Equal(new[] { "foo", "baz", "bar" }, text);
@ -161,8 +161,8 @@ namespace Avalonia.Controls.UnitTests.Presenters
items.Insert(2, "insert");
var text = target.Panel.Children
.OfType<TextBlock>()
.Select(x => x.Text)
.OfType<ContentPresenter>()
.Select(x => x.Content)
.ToList();
Assert.Equal(new[] { "foo", "bar", "insert", "baz" }, text);
@ -195,16 +195,16 @@ namespace Avalonia.Controls.UnitTests.Presenters
target.ApplyTemplate();
var text = target.Panel.Children.Cast<TextBlock>().Select(x => x.Text).ToList();
var text = target.Panel.Children.Cast<ContentPresenter>().Select(x => x.Content).ToList();
Assert.Equal(new[] { "foo", "bar" }, text);
Assert.Equal(new[] { "foo", null, "bar" }, text);
Assert.NotNull(target.ItemContainerGenerator.ContainerFromIndex(0));
Assert.Null(target.ItemContainerGenerator.ContainerFromIndex(1));
Assert.NotNull(target.ItemContainerGenerator.ContainerFromIndex(1));
Assert.NotNull(target.ItemContainerGenerator.ContainerFromIndex(2));
items.RemoveAt(1);
text = target.Panel.Children.Cast<TextBlock>().Select(x => x.Text).ToList();
text = target.Panel.Children.Cast<ContentPresenter>().Select(x => x.Content).ToList();
Assert.Equal(new[] { "foo", "bar" }, text);
Assert.NotNull(target.ItemContainerGenerator.ContainerFromIndex(0));
@ -224,8 +224,11 @@ namespace Avalonia.Controls.UnitTests.Presenters
target.ApplyTemplate();
items.RemoveAt(2);
var text = target.Panel.Children.OfType<TextBlock>().Select(x => x.Text);
Assert.Equal(new[] { "1", "2" }, text);
var numbers = target.Panel.Children
.OfType<ContentPresenter>()
.Select(x => x.Content)
.Cast<int>();
Assert.Equal(new[] { 1, 2 }, numbers);
}
[Fact]
@ -288,8 +291,8 @@ namespace Avalonia.Controls.UnitTests.Presenters
target.ApplyTemplate();
var text = target.Panel.Children
.Cast<TextBlock>()
.Select(x => x.Text)
.Cast<ContentPresenter>()
.Select(x => x.Content)
.ToList();
Assert.Equal(new[] { "Foo", "Bar" }, text);
@ -308,7 +311,7 @@ namespace Avalonia.Controls.UnitTests.Presenters
target.ApplyTemplate();
var dataContexts = target.Panel.Children
.Cast<TextBlock>()
.Cast<ContentPresenter>()
.Select(x => x.DataContext)
.ToList();

16
tests/Avalonia.Controls.UnitTests/TabControlTests.cs

@ -184,23 +184,29 @@ namespace Avalonia.Controls.UnitTests
ApplyTemplate(target);
var carousel = (Carousel)target.Pages;
var dataContext = ((TextBlock)carousel.Presenter.Panel.GetLogicalChildren().Single()).DataContext;
var container = (ContentPresenter)carousel.Presenter.Panel.Children.Single();
container.UpdateChild();
var dataContext = ((TextBlock)container.Child).DataContext;
Assert.Equal(items[0], dataContext);
target.SelectedIndex = 1;
dataContext = ((Button)carousel.Presenter.Panel.GetLogicalChildren().Single()).DataContext;
container = (ContentPresenter)carousel.Presenter.Panel.Children.Single();
container.UpdateChild();
dataContext = ((Button)container.Child).DataContext;
Assert.Equal(items[1], dataContext);
target.SelectedIndex = 2;
dataContext = ((TextBlock)carousel.Presenter.Panel.GetLogicalChildren().Single()).DataContext;
dataContext = ((TextBlock)carousel.Presenter.Panel.Children.Single()).DataContext;
Assert.Equal("Base", dataContext);
target.SelectedIndex = 3;
dataContext = ((TextBlock)carousel.Presenter.Panel.GetLogicalChildren().Single()).DataContext;
container = (ContentPresenter)carousel.Presenter.Panel.Children[0];
container.UpdateChild();
dataContext = ((TextBlock)container.Child).DataContext;
Assert.Equal("Qux", dataContext);
target.SelectedIndex = 4;
dataContext = ((TextBlock)carousel.Presenter.Panel.GetLogicalChildren().Single()).DataContext;
dataContext = ((TextBlock)carousel.Presenter.Panel.Children.Single()).DataContext;
Assert.Equal("Base", dataContext);
}

Loading…
Cancel
Save