From c4cfd967dc83164ec86be631dc0d4622c0049b6b Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 25 Sep 2015 12:09:49 +0200 Subject: [PATCH] Fix DataContexts. This makes it so that IControls are no longer DataTemplate-able, breaking TabControl. Need to find a better way. --- .../Generators/ItemContainerGenerator.cs | 9 +--- .../Generators/ItemContainerGenerator`1.cs | 18 +++++--- .../Presenters/ContentPresenter.cs | 2 +- .../Templates/DataTemplateExtensions.cs | 41 ++++++++++------- .../ItemsControlTests.cs | 44 +++++++++++++++++++ 5 files changed, 84 insertions(+), 30 deletions(-) diff --git a/src/Perspex.Controls/Generators/ItemContainerGenerator.cs b/src/Perspex.Controls/Generators/ItemContainerGenerator.cs index 0e23256c87..51f70fadb6 100644 --- a/src/Perspex.Controls/Generators/ItemContainerGenerator.cs +++ b/src/Perspex.Controls/Generators/ItemContainerGenerator.cs @@ -142,14 +142,7 @@ namespace Perspex.Controls.Generators /// The created container control. protected virtual IControl CreateContainer(object item) { - if (item == null) - { - return null; - } - else - { - return Owner.MaterializeDataTemplate(item); - } + return Owner.MaterializeDataTemplate(item); } /// diff --git a/src/Perspex.Controls/Generators/ItemContainerGenerator`1.cs b/src/Perspex.Controls/Generators/ItemContainerGenerator`1.cs index b943231e62..1f6cbeb6ac 100644 --- a/src/Perspex.Controls/Generators/ItemContainerGenerator`1.cs +++ b/src/Perspex.Controls/Generators/ItemContainerGenerator`1.cs @@ -23,15 +23,23 @@ namespace Perspex.Controls.Generators /// protected override IControl CreateContainer(object item) { - T result = item as T; + var container = item as T; - if (result == null) + if (item == null) { - result = new T(); + return null; + } + else if (container != null) + { + return container; + } + else + { + var result = new T(); result.Content = Owner.MaterializeDataTemplate(item); + result.DataContext = item; + return result; } - - return result; } } } diff --git a/src/Perspex.Controls/Presenters/ContentPresenter.cs b/src/Perspex.Controls/Presenters/ContentPresenter.cs index 0f2f53fde5..6425d51294 100644 --- a/src/Perspex.Controls/Presenters/ContentPresenter.cs +++ b/src/Perspex.Controls/Presenters/ContentPresenter.cs @@ -97,7 +97,7 @@ namespace Perspex.Controls.Presenters { var old = Child; var content = Content; - var result = content != null ? this.MaterializeDataTemplate(content) : null; + var result = this.MaterializeDataTemplate(content); var logicalHost = this.FindReparentingHost(); var logicalChildren = logicalHost?.LogicalChildren ?? LogicalChildren; diff --git a/src/Perspex.Controls/Templates/DataTemplateExtensions.cs b/src/Perspex.Controls/Templates/DataTemplateExtensions.cs index f99fe41d26..8e885ede2d 100644 --- a/src/Perspex.Controls/Templates/DataTemplateExtensions.cs +++ b/src/Perspex.Controls/Templates/DataTemplateExtensions.cs @@ -19,28 +19,37 @@ namespace Perspex.Controls.Templates /// The data materialized as a control. public static IControl MaterializeDataTemplate(this IControl control, object data) { - IDataTemplate template = control.FindDataTemplate(data); - IControl result; - - if (template != null) + if (data == null) { - result = template.Build(data); + return null; + } + else + { + var asControl = data as IControl; - if (result != null && result.DataContext == null) + if (asControl != null) + { + return asControl; + } + else { + IDataTemplate template = control.FindDataTemplate(data); + IControl result; + + if (template != null) + { + result = template.Build(data); + } + else + { + result = DataTemplate.Default.Build(data); + } + result.DataContext = data; + + return result; } } - else if (data is IControl) - { - result = (IControl)data; - } - else - { - result = DataTemplate.Default.Build(data); - } - - return result; } /// diff --git a/tests/Perspex.Controls.UnitTests/ItemsControlTests.cs b/tests/Perspex.Controls.UnitTests/ItemsControlTests.cs index 861624ce14..04559bd5bb 100644 --- a/tests/Perspex.Controls.UnitTests/ItemsControlTests.cs +++ b/tests/Perspex.Controls.UnitTests/ItemsControlTests.cs @@ -287,6 +287,50 @@ namespace Perspex.Controls.UnitTests Assert.Equal(target, ((ILogical)child).LogicalParent); } + [Fact] + public void DataContexts_Should_Be_Correctly_Set() + { + var items = new object[] + { + "Foo", + new Item("Bar"), + new TextBlock { Text = "Baz" }, + new ListBoxItem { Content = "Qux" }, + }; + + var target = new ItemsControl + { + Template = GetTemplate(), + DataContext = "Base", + DataTemplates = new DataTemplates + { + new DataTemplate(x => new Button { Content = x }) + }, + Items = items, + }; + + target.ApplyTemplate(); + + var dataContexts = target.Presenter.Panel.Children + .Cast() + .Select(x => x.DataContext) + .ToList(); + + Assert.Equal( + new object[] { items[0], items[1], "Base", "Base" }, + dataContexts); + } + + private class Item + { + public Item(string value) + { + Value = value; + } + + public string Value { get; } + } + private ControlTemplate GetTemplate() { return new ControlTemplate(parent =>