123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422 |
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Reactive.Linq;
- using Avalonia.Controls.Presenters;
- using Avalonia.Controls.Templates;
- using Avalonia.Data;
- using Avalonia.LogicalTree;
- using Avalonia.Styling;
- using Avalonia.UnitTests;
- using Avalonia.VisualTree;
- using Xunit;
- namespace Avalonia.Controls.UnitTests.Presenters
- {
- /// <summary>
- /// Tests for ContentControls that are hosted in a control template.
- /// </summary>
- public class ContentPresenterTests_InTemplate : ScopedTestBase
- {
- [Fact]
- public void Should_Register_With_Host_When_TemplatedParent_Set()
- {
- var host = new ContentControl();
- var target = new ContentPresenter { Name = "PART_ContentPresenter" };
- Assert.Null(host.Presenter);
- target.TemplatedParent = host;
- Assert.Same(target, host.Presenter);
- }
- [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.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.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 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);
- }
- [Fact]
- public void Should_Not_Bind_Old_Child_To_New_DataContext()
- {
- // Test for issue #1099.
- var textBlock = new TextBlock
- {
- [!TextBlock.TextProperty] = new Binding(),
- };
- var (target, host) = CreateTarget();
- host.DataTemplates.Add(new FuncDataTemplate<string>((_, __) => textBlock));
- host.DataTemplates.Add(new FuncDataTemplate<int>((_, __) => new Canvas()));
- target.Content = "foo";
- Assert.Same(textBlock, target.Child);
- textBlock.PropertyChanged += (s, e) =>
- {
- Assert.NotEqual(e.NewValue, "42");
- };
- target.Content = 42;
- }
- [Fact]
- public void Should_Not_Bind_Child_To_Wrong_DataContext_When_Removing()
- {
- // Test for issue #2823
- var canvas = new Canvas();
- var (target, host) = CreateTarget();
- var viewModel = new TestViewModel { Content = "foo" };
- var dataContexts = new List<object>();
- target.Bind(ContentPresenter.ContentProperty, (IBinding)new TemplateBinding(ContentControl.ContentProperty));
- canvas.GetObservable(ContentPresenter.DataContextProperty).Subscribe(x => dataContexts.Add(x));
- host.DataTemplates.Add(new FuncDataTemplate<string>((_, __) => canvas));
- host.Bind(ContentControl.ContentProperty, new Binding(nameof(TestViewModel.Content)));
- host.DataContext = viewModel;
- Assert.Same(canvas, target.Child);
- viewModel.Content = 42;
- Assert.Equal(new object[]
- {
- null,
- "foo",
- null,
- }, dataContexts);
- }
- [Fact]
- public void Should_Set_InheritanceParent_Even_When_LogicalParent_Is_Already_Set()
- {
- var logicalParent = new Canvas();
- var child = new TextBlock();
- var (target, host) = CreateTarget();
- ((ISetLogicalParent)child).SetParent(logicalParent);
- target.Content = child;
- Assert.Same(logicalParent, child.Parent);
- // InheritanceParent is exposed via StylingParent.
- Assert.Same(target, ((IStyleHost)child).StylingParent);
- }
- [Fact]
- public void Should_Reset_InheritanceParent_When_Child_Removed()
- {
- var logicalParent = new Canvas();
- var child = new TextBlock();
- var (target, _) = CreateTarget();
- ((ISetLogicalParent)child).SetParent(logicalParent);
- target.Content = child;
- target.Content = null;
- // InheritanceParent is exposed via StylingParent.
- Assert.Same(logicalParent, ((IStyleHost)child).StylingParent);
- }
- [Fact]
- public void Should_Clear_Host_When_Host_Template_Cleared()
- {
- var (target, host) = CreateTarget();
- Assert.Same(host, target.Host);
- host.Template = null;
- host.ApplyTemplate();
- Assert.Null(target.Host);
- }
- [Fact]
- public void Content_Should_Become_DataContext_When_ControlTemplate_Is_Not_Null()
- {
- var (target, _) = CreateTarget();
- var textBlock = new TextBlock
- {
- [!TextBlock.TextProperty] = new Binding("Name"),
- };
- var canvas = new Canvas()
- {
- Name = "Canvas"
- };
- target.ContentTemplate = new FuncDataTemplate<Canvas>((_, __) => textBlock);
- target.Content = canvas;
- Assert.NotNull(target.DataContext);
- Assert.Equal(canvas, target.DataContext);
- Assert.Equal("Canvas", textBlock.Text);
- }
- static (ContentPresenter presenter, ContentControl templatedParent) CreateTarget()
- {
- var templatedParent = new ContentControl
- {
- Template = new FuncControlTemplate<ContentControl>((_, s) =>
- new ContentPresenter
- {
- Name = "PART_ContentPresenter",
- }.RegisterInNameScope(s)),
- };
- var root = new TestRoot { Child = templatedParent };
- templatedParent.ApplyTemplate();
- return (templatedParent.Presenter, templatedParent);
- }
- private class TestContentControl : ContentControl, IContentPresenterHost
- {
- public Control Child { get; set; }
- }
- private class TestViewModel : INotifyPropertyChanged
- {
- private object _content;
- public object Content
- {
- get => _content;
- set
- {
- if (_content != value)
- {
- _content = value;
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Content)));
- }
- }
- }
- public event PropertyChangedEventHandler PropertyChanged;
- }
- }
- }
|