Browse Source

Added ContentControl.ContentTemplate.

pull/540/head
Steven Kirk 10 years ago
parent
commit
0e8995e303
  1. 15
      src/Avalonia.Controls/ContentControl.cs
  2. 6
      src/Avalonia.Controls/IContentControl.cs
  3. 17
      src/Avalonia.Controls/Presenters/ContentPresenter.cs
  4. 25
      src/Avalonia.Controls/Templates/DataTemplateExtensions.cs
  5. 3
      src/Avalonia.Themes.Default/ContentControl.xaml
  6. 19
      tests/Avalonia.Controls.UnitTests/ContentControlTests.cs

15
src/Avalonia.Controls/ContentControl.cs

@ -21,6 +21,12 @@ namespace Avalonia.Controls
public static readonly StyledProperty<object> ContentProperty = public static readonly StyledProperty<object> ContentProperty =
AvaloniaProperty.Register<ContentControl, object>(nameof(Content)); AvaloniaProperty.Register<ContentControl, object>(nameof(Content));
/// <summary>
/// Defines the <see cref="ContentTemplate"/> property.
/// </summary>
public static readonly StyledProperty<IDataTemplate> ContentTemplateProperty =
AvaloniaProperty.Register<ContentControl, IDataTemplate>(nameof(ContentTemplate));
/// <summary> /// <summary>
/// Defines the <see cref="HorizontalContentAlignment"/> property. /// Defines the <see cref="HorizontalContentAlignment"/> property.
/// </summary> /// </summary>
@ -51,6 +57,15 @@ namespace Avalonia.Controls
set { SetValue(ContentProperty, value); } set { SetValue(ContentProperty, value); }
} }
/// <summary>
/// Gets or sets the data template used to display the content of the control.
/// </summary>
public IDataTemplate ContentTemplate
{
get { return GetValue(ContentTemplateProperty); }
set { SetValue(ContentTemplateProperty, value); }
}
/// <summary> /// <summary>
/// Gets the presenter from the control's template. /// Gets the presenter from the control's template.
/// </summary> /// </summary>

6
src/Avalonia.Controls/IContentControl.cs

@ -1,6 +1,7 @@
// Copyright (c) The Avalonia Project. All rights reserved. // 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. // Licensed under the MIT license. See licence.md file in the project root for full license information.
using Avalonia.Controls.Templates;
using Avalonia.Layout; using Avalonia.Layout;
namespace Avalonia.Controls namespace Avalonia.Controls
@ -16,6 +17,11 @@ namespace Avalonia.Controls
/// </summary> /// </summary>
object Content { get; set; } object Content { get; set; }
/// <summary>
/// Gets or sets the data template used to display the content of the control.
/// </summary>
IDataTemplate ContentTemplate { get; set; }
/// <summary> /// <summary>
/// Gets or sets the horizontal alignment of the content within the control. /// Gets or sets the horizontal alignment of the content within the control.
/// </summary> /// </summary>

17
src/Avalonia.Controls/Presenters/ContentPresenter.cs

@ -48,6 +48,12 @@ namespace Avalonia.Controls.Presenters
public static readonly StyledProperty<object> ContentProperty = public static readonly StyledProperty<object> ContentProperty =
ContentControl.ContentProperty.AddOwner<ContentPresenter>(); ContentControl.ContentProperty.AddOwner<ContentPresenter>();
/// <summary>
/// Defines the <see cref="ContentTemplate"/> property.
/// </summary>
public static readonly StyledProperty<IDataTemplate> ContentTemplateProperty =
ContentControl.ContentTemplateProperty.AddOwner<ContentPresenter>();
/// <summary> /// <summary>
/// Defines the <see cref="CornerRadius"/> property. /// Defines the <see cref="CornerRadius"/> property.
/// </summary> /// </summary>
@ -140,6 +146,15 @@ namespace Avalonia.Controls.Presenters
set { SetValue(ContentProperty, value); } set { SetValue(ContentProperty, value); }
} }
/// <summary>
/// Gets or sets the data template used to display the content of the control.
/// </summary>
public IDataTemplate ContentTemplate
{
get { return GetValue(ContentTemplateProperty); }
set { SetValue(ContentTemplateProperty, value); }
}
/// <summary> /// <summary>
/// Gets or sets the radius of the border rounded corners. /// Gets or sets the radius of the border rounded corners.
/// </summary> /// </summary>
@ -200,7 +215,7 @@ namespace Avalonia.Controls.Presenters
{ {
var old = Child; var old = Child;
var content = Content; var content = Content;
var result = this.MaterializeDataTemplate(content); var result = this.MaterializeDataTemplate(content, ContentTemplate);
if (old != null) if (old != null)
{ {

25
src/Avalonia.Controls/Templates/DataTemplateExtensions.cs

@ -16,8 +16,15 @@ namespace Avalonia.Controls.Templates
/// </summary> /// </summary>
/// <param name="control">The control materializing the data template.</param> /// <param name="control">The control materializing the data template.</param>
/// <param name="data">The data.</param> /// <param name="data">The data.</param>
/// <param name="primary">
/// An optional primary template that can will be tried before the
/// <see cref="IControl.DataTemplates"/> in the tree are searched.
/// </param>
/// <returns>The data materialized as a control.</returns> /// <returns>The data materialized as a control.</returns>
public static IControl MaterializeDataTemplate(this IControl control, object data) public static IControl MaterializeDataTemplate(
this IControl control,
object data,
IDataTemplate primary = null)
{ {
if (data == null) if (data == null)
{ {
@ -33,7 +40,7 @@ namespace Avalonia.Controls.Templates
} }
else else
{ {
IDataTemplate template = control.FindDataTemplate(data); IDataTemplate template = control.FindDataTemplate(data, primary);
IControl result; IControl result;
if (template != null) if (template != null)
@ -57,9 +64,21 @@ namespace Avalonia.Controls.Templates
/// </summary> /// </summary>
/// <param name="control">The control searching for the data template.</param> /// <param name="control">The control searching for the data template.</param>
/// <param name="data">The data.</param> /// <param name="data">The data.</param>
/// <param name="primary">
/// An optional primary template that can will be tried before the
/// <see cref="IControl.DataTemplates"/> in the tree are searched.
/// </param>
/// <returns>The data template or null if no matching data template was found.</returns> /// <returns>The data template or null if no matching data template was found.</returns>
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<IControl>()) foreach (var i in control.GetSelfAndLogicalAncestors().OfType<IControl>())
{ {
foreach (IDataTemplate dt in i.DataTemplates) foreach (IDataTemplate dt in i.DataTemplates)

3
src/Avalonia.Themes.Default/ContentControl.xaml

@ -5,7 +5,8 @@
Background="{TemplateBinding Background}" Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}" BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}" BorderThickness="{TemplateBinding BorderThickness}"
Content="{TemplateBinding Content}" Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Padding="{TemplateBinding Padding}"/> Padding="{TemplateBinding Padding}"/>
</ControlTemplate> </ControlTemplate>
</Setter> </Setter>

19
tests/Avalonia.Controls.UnitTests/ContentControlTests.cs

@ -116,6 +116,24 @@ namespace Avalonia.Controls.UnitTests
Assert.Equal(new[] { child }, target.GetLogicalChildren()); Assert.Equal(new[] { child }, target.GetLogicalChildren());
} }
[Fact]
public void Should_Use_ContentTemplate_To_Create_Control()
{
var target = new ContentControl
{
Template = GetTemplate(),
ContentTemplate = new FuncDataTemplate<string>(_ => new Canvas()),
};
target.Content = "Foo";
target.ApplyTemplate();
((ContentPresenter)target.Presenter).UpdateChild();
var child = target.Presenter.Child;
Assert.IsType<Canvas>(child);
}
[Fact] [Fact]
public void DataTemplate_Created_Control_Should_Be_Logical_Child_After_ApplyTemplate() public void DataTemplate_Created_Control_Should_Be_Logical_Child_After_ApplyTemplate()
{ {
@ -266,6 +284,7 @@ namespace Avalonia.Controls.UnitTests
{ {
Name = "PART_ContentPresenter", Name = "PART_ContentPresenter",
[~ContentPresenter.ContentProperty] = parent[~ContentControl.ContentProperty], [~ContentPresenter.ContentProperty] = parent[~ContentControl.ContentProperty],
[~ContentPresenter.ContentTemplateProperty] = parent[~ContentControl.ContentTemplateProperty],
} }
}; };
}); });

Loading…
Cancel
Save