Browse Source

Fixed applying control templates.

And added unit tests for it.
pull/72/merge
Steven Kirk 11 years ago
parent
commit
c7dc89f06b
  1. 8
      Perspex.Controls/Presenters/ContentPresenter.cs
  2. 2
      Perspex.Controls/Presenters/ItemsPresenter.cs
  3. 27
      Perspex.Controls/Primitives/TemplatedControl.cs
  4. 2
      Perspex.Layout/ILayoutable.cs
  5. 8
      Tests/Perspex.Controls.UnitTests/ItemsControlTests.cs
  6. 1
      Tests/Perspex.Controls.UnitTests/Perspex.Controls.UnitTests.csproj
  7. 10
      Tests/Perspex.Controls.UnitTests/Presenters/ItemsPresenterTests.cs
  8. 159
      Tests/Perspex.Controls.UnitTests/Primitives/TemplatedControlTests.cs

8
Perspex.Controls/Presenters/ContentPresenter.cs

@ -125,14 +125,6 @@ namespace Perspex.Controls.Presenters
((ISetLogicalParent)result).SetParent(this.logicalParent ?? this);
}
var templatedParent = this.TemplatedParent as TemplatedControl;
if (templatedParent != null)
{
templatedParent = templatedParent.TemplatedParent as TemplatedControl;
}
((Control)result).TemplatedParent = templatedParent;
this.AddVisualChild(result);
this.LogicalChildren.Add(result);
}

2
Perspex.Controls/Presenters/ItemsPresenter.cs

@ -139,7 +139,7 @@ namespace Perspex.Controls.Presenters
{
this.ClearVisualChildren();
this.Panel = this.ItemsPanel.Build();
this.Panel.TemplatedParent = this;
this.Panel.SetValue(TemplatedParentProperty, this.TemplatedParent);
KeyboardNavigation.SetTabNavigation(this.Panel, KeyboardNavigation.GetTabNavigation(this));
this.AddVisualChild(this.Panel);
this.createdPanel = true;

27
Perspex.Controls/Primitives/TemplatedControl.cs

@ -198,15 +198,9 @@ namespace Perspex.Controls.Primitives
this.templateLog.Verbose("Creating control template");
var child = this.Template.Build(this);
this.SetTemplatedParent((Control)child);
this.SetTemplatedParentAndApplyChildTemplates(child);
this.AddVisualChild((Visual)child);
((ISetLogicalParent)child).SetParent(this);
foreach (var i in this.GetTemplateChildren())
{
i.ApplyTemplate();
}
this.OnTemplateApplied();
}
@ -222,19 +216,24 @@ namespace Perspex.Controls.Primitives
}
/// <summary>
/// Sets the <see cref="TemplatedParent"/> property of the control and decendents until
/// an <see cref="IPresenter"/> is found.
/// Sets the TemplatedParent property for a control created from the control template and
/// applies the templates of nested templated controls.
/// </summary>
/// <param name="control">The control.</param>
private void SetTemplatedParent(Control control)
private void SetTemplatedParentAndApplyChildTemplates(IControl control)
{
control.TemplatedParent = this;
if (control.TemplatedParent == null)
{
control.SetValue(TemplatedParentProperty, this);
}
control.ApplyTemplate();
if (!(control is IPresenter))
if (!(control is IPresenter && control.TemplatedParent == this))
{
foreach (var child in control.GetVisualChildren().OfType<Control>())
foreach (IControl child in control.GetVisualChildren())
{
this.SetTemplatedParent(child);
this.SetTemplatedParentAndApplyChildTemplates(child);
}
}
}

2
Perspex.Layout/ILayoutable.cs

@ -35,6 +35,8 @@ namespace Perspex.Layout
Rect? PreviousArrange { get; }
void ApplyTemplate();
void Measure(Size availableSize, bool force = false);
void Arrange(Rect rect, bool force = false);

8
Tests/Perspex.Controls.UnitTests/ItemsControlTests.cs

@ -19,7 +19,7 @@ namespace Perspex.Controls.UnitTests
public class ItemsControlTests
{
[Fact]
public void Panel_Should_Have_TemplatedParent_Set_To_ItemsPresenter()
public void Panel_Should_Have_TemplatedParent_Set_To_ItemsControl()
{
var target = new ItemsControl();
@ -28,9 +28,9 @@ namespace Perspex.Controls.UnitTests
target.ApplyTemplate();
var presenter = target.GetTemplateChildren().OfType<ItemsPresenter>().Single();
var panel = presenter.GetTemplateChildren().OfType<StackPanel>().Single();
var panel = target.GetTemplateChildren().OfType<StackPanel>().Single();
Assert.Equal(presenter, panel.TemplatedParent);
Assert.Equal(target, panel.TemplatedParent);
}
[Fact]
@ -43,7 +43,7 @@ namespace Perspex.Controls.UnitTests
target.ApplyTemplate();
var presenter = target.GetTemplateChildren().OfType<ItemsPresenter>().Single();
var panel = presenter.GetTemplateChildren().OfType<StackPanel>().Single();
var panel = target.GetTemplateChildren().OfType<StackPanel>().Single();
var item = (TextBlock)panel.GetVisualChildren().First();
Assert.Null(item.TemplatedParent);

1
Tests/Perspex.Controls.UnitTests/Perspex.Controls.UnitTests.csproj

@ -98,6 +98,7 @@
<Compile Include="Presenters\DeckPresenterTests.cs" />
<Compile Include="Presenters\ItemsPresenterTests.cs" />
<Compile Include="Presenters\ScrollContentPresenterTests.cs" />
<Compile Include="Primitives\TemplatedControlTests.cs" />
<Compile Include="Primitives\ScrollBarTests.cs" />
<Compile Include="Primitives\RangeBaseTests.cs" />
<Compile Include="Primitives\SelectingItemsControlTests_AutoSelect.cs" />

10
Tests/Perspex.Controls.UnitTests/Presenters/ItemsPresenterTests.cs

@ -144,16 +144,6 @@ namespace Perspex.Controls.UnitTests.Presenters
Assert.Equal(panel, target.Panel);
}
[Fact]
public void Panel_TemplatedParent_Should_Be_Set()
{
var target = new ItemsPresenter();
target.ApplyTemplate();
Assert.Equal(target, target.Panel.TemplatedParent);
}
[Fact]
public void Panel_TabNavigation_Should_Be_Set_To_Once()
{

159
Tests/Perspex.Controls.UnitTests/Primitives/TemplatedControlTests.cs

@ -0,0 +1,159 @@
// -----------------------------------------------------------------------
// <copyright file="TemplatedControlTests.cs" company="Steven Kirk">
// Copyright 2015 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls.UnitTests.Primitives
{
using System;
using System.Linq;
using Collections;
using Perspex.Controls.Presenters;
using Perspex.Controls.Primitives;
using Perspex.Controls.Templates;
using Perspex.LogicalTree;
using Perspex.VisualTree;
using Xunit;
public class TemplatedControlTests
{
[Fact]
public void ApplyTemplate_Should_Create_Visual_Child()
{
var target = new TemplatedControl
{
Template = new ControlTemplate(_ => new Decorator
{
Child = new Panel
{
Children = new Controls
{
new TextBlock(),
new Border(),
}
}
}),
};
target.ApplyTemplate();
var types = target.GetVisualDescendents().Select(x => x.GetType()).ToList();
Assert.Equal(
new[]
{
typeof(Decorator),
typeof(Panel),
typeof(TextBlock),
typeof(Border)
},
types);
Assert.Empty(target.GetLogicalChildren());
}
[Fact]
public void Templated_Children_Should_Have_TemplatedParent_Set()
{
var target = new TemplatedControl
{
Template = new ControlTemplate(_ => new Decorator
{
Child = new Panel
{
Children = new Controls
{
new TextBlock(),
new Border(),
}
}
}),
};
target.ApplyTemplate();
var templatedParents = target.GetVisualDescendents()
.OfType<IControl>()
.Select(x => x.TemplatedParent)
.ToList();
Assert.Equal(4, templatedParents.Count);
Assert.True(templatedParents.All(x => x == target));
}
[Fact]
public void Nested_TemplatedControls_Should_Be_Expanded_And_Have_Correct_TemplatedParent()
{
var target = new ItemsControl
{
Template = new ControlTemplate<ItemsControl>(ItemsControlTemplate),
Items = new[] { "Foo", }
};
target.ApplyTemplate();
var scrollViewer = target.GetVisualDescendents()
.OfType<ScrollViewer>()
.Single();
var types = target.GetVisualDescendents()
.Select(x => x.GetType())
.ToList();
var templatedParents = target.GetVisualDescendents()
.OfType<IControl>()
.Select(x => x.TemplatedParent)
.ToList();
Assert.Equal(
new[]
{
typeof(Border),
typeof(ScrollViewer),
typeof(ScrollContentPresenter),
typeof(ItemsPresenter),
typeof(StackPanel),
typeof(TextBlock),
},
types);
Assert.Equal(
new object[]
{
target,
target,
scrollViewer,
target,
target,
null
},
templatedParents);
}
private static IControl ItemsControlTemplate(ItemsControl control)
{
return new Border
{
Child = new ScrollViewer
{
Template = new ControlTemplate<ScrollViewer>(ScrollViewerTemplate),
Content = new ItemsPresenter
{
Name = "itemsPresenter",
[~ItemsPresenter.ItemsProperty] = control[~ListBox.ItemsProperty],
[~ItemsPresenter.ItemsPanelProperty] = control[~ListBox.ItemsPanelProperty],
}
}
};
}
private static Control ScrollViewerTemplate(ScrollViewer control)
{
var result = new ScrollContentPresenter
{
Name = "contentPresenter",
[~ScrollContentPresenter.ContentProperty] = control[~ScrollViewer.ContentProperty],
};
return result;
}
}
}
Loading…
Cancel
Save