From 0e8995e303e97d5fc44a2bd581a670d520489ec7 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Thu, 19 May 2016 22:13:29 +0100 Subject: [PATCH] Added ContentControl.ContentTemplate. --- src/Avalonia.Controls/ContentControl.cs | 15 +++++++++++ src/Avalonia.Controls/IContentControl.cs | 6 +++++ .../Presenters/ContentPresenter.cs | 17 ++++++++++++- .../Templates/DataTemplateExtensions.cs | 25 ++++++++++++++++--- .../ContentControl.xaml | 3 ++- .../ContentControlTests.cs | 19 ++++++++++++++ 6 files changed, 80 insertions(+), 5 deletions(-) diff --git a/src/Avalonia.Controls/ContentControl.cs b/src/Avalonia.Controls/ContentControl.cs index 822d9da11a..0eba3c13ae 100644 --- a/src/Avalonia.Controls/ContentControl.cs +++ b/src/Avalonia.Controls/ContentControl.cs @@ -21,6 +21,12 @@ namespace Avalonia.Controls public static readonly StyledProperty ContentProperty = AvaloniaProperty.Register(nameof(Content)); + /// + /// Defines the property. + /// + public static readonly StyledProperty ContentTemplateProperty = + AvaloniaProperty.Register(nameof(ContentTemplate)); + /// /// Defines the property. /// @@ -51,6 +57,15 @@ namespace Avalonia.Controls set { SetValue(ContentProperty, value); } } + /// + /// Gets or sets the data template used to display the content of the control. + /// + public IDataTemplate ContentTemplate + { + get { return GetValue(ContentTemplateProperty); } + set { SetValue(ContentTemplateProperty, value); } + } + /// /// Gets the presenter from the control's template. /// diff --git a/src/Avalonia.Controls/IContentControl.cs b/src/Avalonia.Controls/IContentControl.cs index d09f5bd9c6..863c132778 100644 --- a/src/Avalonia.Controls/IContentControl.cs +++ b/src/Avalonia.Controls/IContentControl.cs @@ -1,6 +1,7 @@ // 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 Avalonia.Controls.Templates; using Avalonia.Layout; namespace Avalonia.Controls @@ -16,6 +17,11 @@ namespace Avalonia.Controls /// object Content { get; set; } + /// + /// Gets or sets the data template used to display the content of the control. + /// + IDataTemplate ContentTemplate { get; set; } + /// /// Gets or sets the horizontal alignment of the content within the control. /// diff --git a/src/Avalonia.Controls/Presenters/ContentPresenter.cs b/src/Avalonia.Controls/Presenters/ContentPresenter.cs index 7f51229061..3470a43c1c 100644 --- a/src/Avalonia.Controls/Presenters/ContentPresenter.cs +++ b/src/Avalonia.Controls/Presenters/ContentPresenter.cs @@ -48,6 +48,12 @@ namespace Avalonia.Controls.Presenters public static readonly StyledProperty ContentProperty = ContentControl.ContentProperty.AddOwner(); + /// + /// Defines the property. + /// + public static readonly StyledProperty ContentTemplateProperty = + ContentControl.ContentTemplateProperty.AddOwner(); + /// /// Defines the property. /// @@ -140,6 +146,15 @@ namespace Avalonia.Controls.Presenters set { SetValue(ContentProperty, value); } } + /// + /// Gets or sets the data template used to display the content of the control. + /// + public IDataTemplate ContentTemplate + { + get { return GetValue(ContentTemplateProperty); } + set { SetValue(ContentTemplateProperty, value); } + } + /// /// Gets or sets the radius of the border rounded corners. /// @@ -200,7 +215,7 @@ namespace Avalonia.Controls.Presenters { var old = Child; var content = Content; - var result = this.MaterializeDataTemplate(content); + var result = this.MaterializeDataTemplate(content, ContentTemplate); if (old != null) { diff --git a/src/Avalonia.Controls/Templates/DataTemplateExtensions.cs b/src/Avalonia.Controls/Templates/DataTemplateExtensions.cs index 782386df6a..9eff4243b1 100644 --- a/src/Avalonia.Controls/Templates/DataTemplateExtensions.cs +++ b/src/Avalonia.Controls/Templates/DataTemplateExtensions.cs @@ -16,8 +16,15 @@ namespace Avalonia.Controls.Templates /// /// The control materializing the data template. /// The data. + /// + /// An optional primary template that can will be tried before the + /// in the tree are searched. + /// /// The data materialized as a control. - public static IControl MaterializeDataTemplate(this IControl control, object data) + public static IControl MaterializeDataTemplate( + this IControl control, + object data, + IDataTemplate primary = null) { if (data == null) { @@ -33,7 +40,7 @@ namespace Avalonia.Controls.Templates } else { - IDataTemplate template = control.FindDataTemplate(data); + IDataTemplate template = control.FindDataTemplate(data, primary); IControl result; if (template != null) @@ -57,9 +64,21 @@ namespace Avalonia.Controls.Templates /// /// The control searching for the data template. /// The data. + /// + /// An optional primary template that can will be tried before the + /// in the tree are searched. + /// /// The data template or null if no matching data template was found. - public static IDataTemplate FindDataTemplate(this IControl control, object data) + public static IDataTemplate FindDataTemplate( + this IControl control, + object data, + IDataTemplate primary = null) { + if (primary?.Match(data) == true) + { + return primary; + } + foreach (var i in control.GetSelfAndLogicalAncestors().OfType()) { foreach (IDataTemplate dt in i.DataTemplates) diff --git a/src/Avalonia.Themes.Default/ContentControl.xaml b/src/Avalonia.Themes.Default/ContentControl.xaml index 1af449a447..27f6648548 100644 --- a/src/Avalonia.Themes.Default/ContentControl.xaml +++ b/src/Avalonia.Themes.Default/ContentControl.xaml @@ -5,7 +5,8 @@ Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" - Content="{TemplateBinding Content}" + Content="{TemplateBinding Content}" + ContentTemplate="{TemplateBinding ContentTemplate}" Padding="{TemplateBinding Padding}"/> diff --git a/tests/Avalonia.Controls.UnitTests/ContentControlTests.cs b/tests/Avalonia.Controls.UnitTests/ContentControlTests.cs index 2ebdfc628c..5f86b9878d 100644 --- a/tests/Avalonia.Controls.UnitTests/ContentControlTests.cs +++ b/tests/Avalonia.Controls.UnitTests/ContentControlTests.cs @@ -116,6 +116,24 @@ namespace Avalonia.Controls.UnitTests Assert.Equal(new[] { child }, target.GetLogicalChildren()); } + [Fact] + public void Should_Use_ContentTemplate_To_Create_Control() + { + var target = new ContentControl + { + Template = GetTemplate(), + ContentTemplate = new FuncDataTemplate(_ => new Canvas()), + }; + + target.Content = "Foo"; + target.ApplyTemplate(); + ((ContentPresenter)target.Presenter).UpdateChild(); + + var child = target.Presenter.Child; + + Assert.IsType(child); + } + [Fact] public void DataTemplate_Created_Control_Should_Be_Logical_Child_After_ApplyTemplate() { @@ -266,6 +284,7 @@ namespace Avalonia.Controls.UnitTests { Name = "PART_ContentPresenter", [~ContentPresenter.ContentProperty] = parent[~ContentControl.ContentProperty], + [~ContentPresenter.ContentTemplateProperty] = parent[~ContentControl.ContentTemplateProperty], } }; });