|
|
@@ -0,0 +1,291 @@
|
|
|
+// Copyright (c) The Avalonia Project. All rights reserved.
|
|
|
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|
|
+
|
|
|
+using System.Linq;
|
|
|
+using Avalonia.Controls.Presenters;
|
|
|
+using Avalonia.Controls.Templates;
|
|
|
+using Avalonia.LogicalTree;
|
|
|
+using Avalonia.UnitTests;
|
|
|
+using Avalonia.VisualTree;
|
|
|
+using Moq;
|
|
|
+using Xunit;
|
|
|
+
|
|
|
+namespace Avalonia.Controls.UnitTests.Presenters
|
|
|
+{
|
|
|
+ /// <summary>
|
|
|
+ /// Tests for ContentControls that are hosted in a control template.
|
|
|
+ /// </summary>
|
|
|
+ public class ContentPresenterTests_InTemplate
|
|
|
+ {
|
|
|
+ [Fact]
|
|
|
+ public void Should_Register_With_Host_When_TemplatedParent_Set()
|
|
|
+ {
|
|
|
+ var host = new Mock<IContentPresenterHost>();
|
|
|
+ var target = new ContentPresenter();
|
|
|
+
|
|
|
+ target.SetValue(Control.TemplatedParentProperty, host.Object);
|
|
|
+
|
|
|
+ host.Verify(x => x.RegisterContentPresenter(target));
|
|
|
+ }
|
|
|
+
|
|
|
+ [Fact]
|
|
|
+ public void Setting_Content_To_Control_Should_Set_Child()
|
|
|
+ {
|
|
|
+ var (target, _) = CreateTarget();
|
|
|
+ var child = new Border();
|
|
|
+
|
|
|
+ target.Content = child;
|
|
|
+
|
|
|
+ Assert.Equal(child, target.Child);
|
|
|
+ }
|
|
|
+
|
|
|
+ [Fact]
|
|
|
+ public void Setting_Content_To_Control_Should_Update_Logical_Tree()
|
|
|
+ {
|
|
|
+ var (target, parent) = CreateTarget();
|
|
|
+ var child = new Border();
|
|
|
+
|
|
|
+ target.Content = child;
|
|
|
+
|
|
|
+ Assert.Equal(parent, child.GetLogicalParent());
|
|
|
+ Assert.Equal(new[] { child }, parent.GetLogicalChildren());
|
|
|
+ }
|
|
|
+
|
|
|
+ [Fact]
|
|
|
+ public void Setting_Content_To_Control_Should_Update_Visual_Tree()
|
|
|
+ {
|
|
|
+ var (target, _) = CreateTarget();
|
|
|
+ var child = new Border();
|
|
|
+
|
|
|
+ target.Content = child;
|
|
|
+
|
|
|
+ Assert.Equal(target, child.GetVisualParent());
|
|
|
+ Assert.Equal(new[] { child }, target.GetVisualChildren());
|
|
|
+ }
|
|
|
+
|
|
|
+ [Fact]
|
|
|
+ public void Setting_Content_To_String_Should_Create_TextBlock()
|
|
|
+ {
|
|
|
+ var (target, _) = CreateTarget();
|
|
|
+
|
|
|
+ target.Content = "Foo";
|
|
|
+
|
|
|
+ Assert.IsType<TextBlock>(target.Child);
|
|
|
+ Assert.Equal("Foo", ((TextBlock)target.Child).Text);
|
|
|
+ }
|
|
|
+
|
|
|
+ [Fact]
|
|
|
+ public void Setting_Content_To_String_Should_Update_Logical_Tree()
|
|
|
+ {
|
|
|
+ var (target, parent) = CreateTarget();
|
|
|
+
|
|
|
+ target.Content = "Foo";
|
|
|
+
|
|
|
+ var child = target.Child;
|
|
|
+ Assert.Equal(parent, child.GetLogicalParent());
|
|
|
+ Assert.Equal(new[] { child }, parent.GetLogicalChildren());
|
|
|
+ }
|
|
|
+
|
|
|
+ [Fact]
|
|
|
+ public void Setting_Content_To_String_Should_Update_Visual_Tree()
|
|
|
+ {
|
|
|
+ var (target, _) = CreateTarget();
|
|
|
+
|
|
|
+ target.Content = "Foo";
|
|
|
+
|
|
|
+ var child = target.Child;
|
|
|
+ Assert.Equal(target, child.GetVisualParent());
|
|
|
+ Assert.Equal(new[] { child }, target.GetVisualChildren());
|
|
|
+ }
|
|
|
+
|
|
|
+ [Fact]
|
|
|
+ public void Clearing_Control_Content_Should_Update_Logical_Tree()
|
|
|
+ {
|
|
|
+ var (target, _) = CreateTarget();
|
|
|
+ var child = new Border();
|
|
|
+
|
|
|
+ target.Content = child;
|
|
|
+ target.Content = null;
|
|
|
+
|
|
|
+ Assert.Equal(null, child.GetLogicalParent());
|
|
|
+ Assert.Empty(target.GetLogicalChildren());
|
|
|
+ }
|
|
|
+
|
|
|
+ [Fact]
|
|
|
+ public void Clearing_Control_Content_Should_Update_Visual_Tree()
|
|
|
+ {
|
|
|
+ var (target, _) = CreateTarget();
|
|
|
+ var child = new Border();
|
|
|
+
|
|
|
+ target.Content = child;
|
|
|
+ target.Content = null;
|
|
|
+
|
|
|
+ Assert.Equal(null, child.GetVisualParent());
|
|
|
+ Assert.Empty(target.GetVisualChildren());
|
|
|
+ }
|
|
|
+
|
|
|
+ [Fact]
|
|
|
+ public void Control_Content_Should_Not_Be_NameScope()
|
|
|
+ {
|
|
|
+ var (target, _) = CreateTarget();
|
|
|
+
|
|
|
+ target.Content = new TextBlock();
|
|
|
+
|
|
|
+ Assert.IsType<TextBlock>(target.Child);
|
|
|
+ Assert.Null(NameScope.GetNameScope((Control)target.Child));
|
|
|
+ }
|
|
|
+
|
|
|
+ [Fact]
|
|
|
+ public void DataTemplate_Created_Control_Should_Be_NameScope()
|
|
|
+ {
|
|
|
+ var (target, _) = CreateTarget();
|
|
|
+
|
|
|
+ target.Content = "Foo";
|
|
|
+
|
|
|
+ Assert.IsType<TextBlock>(target.Child);
|
|
|
+ Assert.NotNull(NameScope.GetNameScope((Control)target.Child));
|
|
|
+ }
|
|
|
+
|
|
|
+ [Fact]
|
|
|
+ public void Assigning_Control_To_Content_Should_Not_Set_DataContext()
|
|
|
+ {
|
|
|
+ var (target, _) = CreateTarget();
|
|
|
+ target.Content = new Border();
|
|
|
+
|
|
|
+ Assert.False(target.IsSet(Control.DataContextProperty));
|
|
|
+ }
|
|
|
+
|
|
|
+ [Fact]
|
|
|
+ public void Assigning_NonControl_To_Content_Should_Set_DataContext_On_UpdateChild()
|
|
|
+ {
|
|
|
+ var (target, _) = CreateTarget();
|
|
|
+ target.Content = "foo";
|
|
|
+
|
|
|
+ Assert.Equal("foo", target.DataContext);
|
|
|
+ }
|
|
|
+
|
|
|
+ [Fact]
|
|
|
+ public void Should_Use_ContentTemplate_If_Specified()
|
|
|
+ {
|
|
|
+ var (target, _) = CreateTarget();
|
|
|
+
|
|
|
+ target.ContentTemplate = new FuncDataTemplate<string>(_ => new Canvas());
|
|
|
+ target.Content = "Foo";
|
|
|
+
|
|
|
+ Assert.IsType<Canvas>(target.Child);
|
|
|
+ }
|
|
|
+
|
|
|
+ [Fact]
|
|
|
+ public void Should_Update_If_ContentTemplate_Changed()
|
|
|
+ {
|
|
|
+ var (target, _) = CreateTarget();
|
|
|
+
|
|
|
+ target.Content = "Foo";
|
|
|
+ Assert.IsType<TextBlock>(target.Child);
|
|
|
+
|
|
|
+ target.ContentTemplate = new FuncDataTemplate<string>(_ => new Canvas());
|
|
|
+ Assert.IsType<Canvas>(target.Child);
|
|
|
+
|
|
|
+ target.ContentTemplate = null;
|
|
|
+ Assert.IsType<TextBlock>(target.Child);
|
|
|
+ }
|
|
|
+
|
|
|
+ [Fact]
|
|
|
+ public void Assigning_Control_To_Content_After_NonControl_Should_Clear_DataContext()
|
|
|
+ {
|
|
|
+ var (target, _) = CreateTarget();
|
|
|
+
|
|
|
+ target.Content = "foo";
|
|
|
+
|
|
|
+ Assert.True(target.IsSet(Control.DataContextProperty));
|
|
|
+
|
|
|
+ target.Content = new Border();
|
|
|
+
|
|
|
+ Assert.False(target.IsSet(Control.DataContextProperty));
|
|
|
+ }
|
|
|
+
|
|
|
+ [Fact]
|
|
|
+ public void Recycles_DataTemplate()
|
|
|
+ {
|
|
|
+ var (target, _) = CreateTarget();
|
|
|
+ target.DataTemplates.Add(new FuncDataTemplate<string>(_ => new Border(), true));
|
|
|
+
|
|
|
+ target.Content = "foo";
|
|
|
+
|
|
|
+ var control = target.Child;
|
|
|
+ Assert.IsType<Border>(control);
|
|
|
+
|
|
|
+ target.Content = "bar";
|
|
|
+ Assert.Same(control, target.Child);
|
|
|
+ }
|
|
|
+
|
|
|
+ [Fact]
|
|
|
+ public void Detects_DataTemplate_Doesnt_Match_And_Doesnt_Recycle()
|
|
|
+ {
|
|
|
+ var (target, _) = CreateTarget();
|
|
|
+ target.DataTemplates.Add(new FuncDataTemplate<string>(x => x == "foo", _ => new Border(), true));
|
|
|
+
|
|
|
+ target.Content = "foo";
|
|
|
+
|
|
|
+ var control = target.Child;
|
|
|
+ Assert.IsType<Border>(control);
|
|
|
+
|
|
|
+ target.Content = "bar";
|
|
|
+ Assert.IsType<TextBlock>(target.Child);
|
|
|
+ }
|
|
|
+
|
|
|
+ [Fact]
|
|
|
+ public void Detects_DataTemplate_Doesnt_Support_Recycling()
|
|
|
+ {
|
|
|
+ var (target, _) = CreateTarget();
|
|
|
+ target.DataTemplates.Add(new FuncDataTemplate<string>(_ => new Border(), false));
|
|
|
+
|
|
|
+ target.Content = "foo";
|
|
|
+
|
|
|
+ var control = target.Child;
|
|
|
+ Assert.IsType<Border>(control);
|
|
|
+
|
|
|
+ target.Content = "bar";
|
|
|
+ Assert.NotSame(control, target.Child);
|
|
|
+ }
|
|
|
+
|
|
|
+ [Fact]
|
|
|
+ public void Reevaluates_DataTemplates_When_Recycling()
|
|
|
+ {
|
|
|
+ var (target, _) = CreateTarget();
|
|
|
+
|
|
|
+ target.DataTemplates.Add(new FuncDataTemplate<string>(x => x == "bar", _ => new Canvas(), true));
|
|
|
+ target.DataTemplates.Add(new FuncDataTemplate<string>(_ => new Border(), true));
|
|
|
+
|
|
|
+ target.Content = "foo";
|
|
|
+
|
|
|
+ var control = target.Child;
|
|
|
+ Assert.IsType<Border>(control);
|
|
|
+
|
|
|
+ target.Content = "bar";
|
|
|
+ Assert.IsType<Canvas>(target.Child);
|
|
|
+ }
|
|
|
+
|
|
|
+ (ContentPresenter presenter, ContentControl templatedParent) CreateTarget()
|
|
|
+ {
|
|
|
+ var templatedParent = new ContentControl
|
|
|
+ {
|
|
|
+ Template = new FuncControlTemplate<ContentControl>(x =>
|
|
|
+ new ContentPresenter
|
|
|
+ {
|
|
|
+ Name = "PART_ContentPresenter",
|
|
|
+ }),
|
|
|
+ };
|
|
|
+ var root = new TestRoot { Child = templatedParent };
|
|
|
+
|
|
|
+ templatedParent.ApplyTemplate();
|
|
|
+
|
|
|
+ return ((ContentPresenter)templatedParent.Presenter, templatedParent);
|
|
|
+ }
|
|
|
+
|
|
|
+ private class TestContentControl : ContentControl
|
|
|
+ {
|
|
|
+ public IControl Child { get; set; }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|