using System; using System.Collections.Generic; using System.Linq; using System.Xml; using Avalonia.Controls; using Avalonia.Controls.Metadata; using Avalonia.Controls.Presenters; using Avalonia.Controls.Primitives; using Avalonia.Controls.Templates; using Avalonia.Data; using Avalonia.Diagnostics; using Avalonia.Markup.Xaml.Templates; using Avalonia.Media; using Avalonia.Metadata; using Avalonia.UnitTests; using Avalonia.VisualTree; using Xunit; namespace Avalonia.Markup.Xaml.UnitTests.Xaml { public class ControlTemplateTests : XamlTestBase { [Fact] public void StyledProperties_Should_Be_Set_In_The_ControlTemplate() { using (UnitTestApplication.Start(TestServices.StyledWindow)) { var xaml = @" "; var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml); var button = (Button)window.Content!; window.ApplyTemplate(); button.ApplyTemplate(); var listBoxHierarchyLine = button.GetVisualChildren().ElementAt(0) as ListBoxHierarchyLine; Assert.NotNull(listBoxHierarchyLine); Assert.NotNull(listBoxHierarchyLine.LineDashStyle); Assert.NotNull(listBoxHierarchyLine.LineDashStyle.Dashes); Assert.Equal(1, listBoxHierarchyLine.LineDashStyle.Offset); Assert.Equal(2, listBoxHierarchyLine.LineDashStyle.Dashes.Count); Assert.Equal(2, listBoxHierarchyLine.LineDashStyle.Dashes[0]); Assert.Equal(2, listBoxHierarchyLine.LineDashStyle.Dashes[1]); } } [Fact] public void Inline_ControlTemplate_Styled_Values_Are_Set_With_Style_Priority() { using (UnitTestApplication.Start(TestServices.StyledWindow)) { var xaml = @" "; var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml); var button = (Button)window.Content!; window.ApplyTemplate(); button.ApplyTemplate(); var presenter = button.Presenter!; Assert.Equal(Brushes.Red, presenter.Background); var diagnostic = presenter.GetDiagnostic(Button.BackgroundProperty); Assert.Equal(BindingPriority.Template, diagnostic.Priority); } } [Fact] public void Style_ControlTemplate_Styled_Values_Are_Set_With_Style_Priority() { using (UnitTestApplication.Start(TestServices.StyledWindow)) { var xaml = @" "; var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml); var button = (Button)window.Content!; window.ApplyTemplate(); button.ApplyTemplate(); var presenter = button.Presenter; Assert.NotNull(presenter); Assert.Equal(Dock.Top, DockPanel.GetDock(presenter)); var diagnostic = presenter.GetDiagnostic(DockPanel.DockProperty); Assert.Equal(BindingPriority.Template, diagnostic.Priority); } } [Fact] public void ControlTemplate_StaticResources_Are_Set_With_Style_Priority() { using (UnitTestApplication.Start(TestServices.StyledWindow)) { var xaml = @" Red "; var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml); var button = (Button)window.Content!; window.ApplyTemplate(); button.ApplyTemplate(); var presenter = button.Presenter; Assert.NotNull(presenter); Assert.Equal(Brushes.Red, presenter.Background); var diagnostic = presenter.GetDiagnostic(Button.BackgroundProperty); Assert.Equal(BindingPriority.Template, diagnostic.Priority); } } [Fact] public void ControlTemplate_DynamicResources_Are_Set_With_Style_Priority() { using (UnitTestApplication.Start(TestServices.StyledWindow)) { var xaml = @" Red "; var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml); var button = (Button)window.Content!; window.ApplyTemplate(); button.ApplyTemplate(); var presenter = button.Presenter; Assert.NotNull(presenter); Assert.Equal(Brushes.Red, presenter.Background); var diagnostic = presenter.GetDiagnostic(Button.BackgroundProperty); Assert.Equal(BindingPriority.Template, diagnostic.Priority); } } [Fact] public void ControlTemplate_TemplateBindings_Are_Set_With_TemplatedParent_Priority() { using (UnitTestApplication.Start(TestServices.StyledWindow)) { var xaml = @" "; var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml); var button = (Button)window.Content!; window.ApplyTemplate(); button.ApplyTemplate(); var presenter = button.Presenter; Assert.NotNull(presenter); Assert.Equal("Foo", presenter.Content); var diagnostic = presenter.GetDiagnostic(ContentPresenter.ContentProperty); Assert.Equal(BindingPriority.Template, diagnostic.Priority); } } [Fact] public void ControlTemplate_With_Nested_Child_Is_Operational() { var xaml = @" "; var template = AvaloniaRuntimeXamlLoader.Parse(xaml); var parent = (ContentControl)template.Build(new ContentControl())!.Result; Assert.Equal("parent", parent.Name); var child = parent.Content as ContentControl; Assert.NotNull(child); Assert.Equal("child", child.Name); } [Fact] public void ControlTemplate_With_TargetType_Is_Operational() { var xaml = @" "; var template = AvaloniaRuntimeXamlLoader.Parse(xaml); Assert.Equal(typeof(ContentControl), template.TargetType); Assert.IsType(typeof(ContentPresenter), template.Build(new ContentControl())!.Result); } [Fact] public void ControlTemplate_With_String_TargetType() { var xaml = @" "; var template = AvaloniaRuntimeXamlLoader.Parse(xaml); Assert.Equal(typeof(ContentControl), template.TargetType); Assert.IsType(typeof(ContentPresenter), template.Build(new ContentControl())!.Result); } [Fact] public void ControlTemplate_With_Panel_Children_Are_Added() { var xaml = @" "; var template = AvaloniaRuntimeXamlLoader.Parse(xaml); var panel = (Panel)template.Build(new ContentControl())!.Result; Assert.Equal(2, panel.Children.Count); var foo = panel.Children[0]; var bar = panel.Children[1]; Assert.Equal("Foo", foo.Name); Assert.Equal("Bar", bar.Name); } [Fact] public void ControlTemplate_Can_Be_Empty() { var xaml = ""; var template = AvaloniaRuntimeXamlLoader.Parse(xaml); var templateResult = template.Build(new TemplatedControl()); Assert.Null(templateResult); } [Fact] public void ControlTemplate_Outputs_Error_When_Missing_TemplatePart() { using var _ = UnitTestApplication.Start(TestServices.StyledWindow); var xaml = @" "; var diagnostics = new List(); AvaloniaRuntimeXamlLoader.Load(new RuntimeXamlLoaderDocument(xaml), new RuntimeXamlLoaderConfiguration { LocalAssembly = typeof(XamlIlTests).Assembly, DiagnosticHandler = diagnostic => { diagnostics.Add(diagnostic); return diagnostic.Severity; } }); var warning = Assert.Single(diagnostics); Assert.Equal(RuntimeXamlDiagnosticSeverity.Info, warning.Severity); Assert.Contains("'PART_MainContentBorder'", warning.Title); } [Fact] public void ControlTemplate_Outputs_Error_When_Using_Wrong_Type_With_TemplatePart() { using var _ = UnitTestApplication.Start(TestServices.StyledWindow); var xaml = @" "; var diagnostics = new List(); Assert.ThrowsAny(() => AvaloniaRuntimeXamlLoader.Load(new RuntimeXamlLoaderDocument(xaml), new RuntimeXamlLoaderConfiguration { LocalAssembly = typeof(XamlIlTests).Assembly, DiagnosticHandler = diagnostic => { diagnostics.Add(diagnostic); return diagnostic.Severity; } })); var warning = Assert.Single(diagnostics); Assert.Equal(RuntimeXamlDiagnosticSeverity.Error, warning.Severity); Assert.Contains("'ContentPresenter'", warning.Title); } [Fact] public void ControlTemplate_Outputs_Error_When_Missing_TemplatePart_Nested_ItemTemplate_Case() { using var _ = UnitTestApplication.Start(TestServices.StyledWindow); var xaml = @" "; var diagnostics = new List(); AvaloniaRuntimeXamlLoader.Load(new RuntimeXamlLoaderDocument(xaml), new RuntimeXamlLoaderConfiguration { LocalAssembly = typeof(XamlIlTests).Assembly, DiagnosticHandler = diagnostic => { diagnostics.Add(diagnostic); return diagnostic.Severity; } }); var warning = Assert.Single(diagnostics); Assert.Equal(RuntimeXamlDiagnosticSeverity.Info, warning.Severity); Assert.Contains("'PART_MainContentBorder'", warning.Title); } [Fact] public void Custom_ControlTemplate_Allows_TemplateBindings() { using (UnitTestApplication.Start(TestServices.StyledWindow)) { var window = (Window)AvaloniaRuntimeXamlLoader.Load( """ """); var button = Assert.IsType