Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Always propagate the BC to the ControlTemplate #26072

Merged
merged 4 commits into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 11 additions & 15 deletions src/Controls/src/Core/ContentView/ContentView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,31 +22,27 @@ protected override void OnBindingContextChanged()
{
base.OnBindingContextChanged();

IView content = Content;

if (content == null && (this as IContentView)?.PresentedContent is IView presentedContent)
content = presentedContent;

ControlTemplate controlTemplate = ControlTemplate;

if (content is BindableObject bindableContent && controlTemplate != null)
SetInheritedBindingContext(bindableContent, BindingContext);
if (Content is View content)
{
SetInheritedBindingContext(content, BindingContext);
}
}

internal override void OnControlTemplateChanged(ControlTemplate oldValue, ControlTemplate newValue)
{
if (oldValue == null)
return;

base.OnControlTemplateChanged(oldValue, newValue);
View content = Content;
ControlTemplate controlTemplate = ControlTemplate;
if (content != null && controlTemplate != null)

if (Content is View content)
{
SetInheritedBindingContext(content, BindingContext);
}
}

internal override void SetChildInheritedBindingContext(Element child, object context)
{
SetInheritedBindingContext(child, context);
}

object IContentView.Content => Content;

IView IContentView.PresentedContent => ((this as IControlTemplated).TemplateRoot as IView) ?? Content;
Expand Down
64 changes: 60 additions & 4 deletions src/Controls/tests/Core.UnitTests/ContentViewUnitTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ public void PacksContent()
}

[Fact]
public void DoesNotInheritBindingContextToTemplate()
public void DoesInheritBindingContextToTemplate()
{
var contentView = new ContentView();
var child = new View();
Expand All @@ -326,8 +326,38 @@ public void DoesNotInheritBindingContextToTemplate()
var bc = "Test";
contentView.BindingContext = bc;

Assert.NotEqual(bc, ((IElementController)contentView).LogicalChildren[0].BindingContext);
Assert.Null(((IElementController)contentView).LogicalChildren[0].BindingContext);
Assert.Equal(bc, ((IElementController)contentView).LogicalChildren[0].BindingContext);
}

[Fact]
public void DoesNotInheritBindingContextToContentFromControlTemplate()
{
var contentView = new ContentView();
var child1 = new View();
var child2 = new View();

contentView.ControlTemplate = new ControlTemplate(typeof(SimpleTemplate));
contentView.Content = child1;

var bcContentView = "Test";
var bcSimpleTemplate = "other context";
contentView.BindingContext = bcContentView;

var simpleTemplate = contentView.GetVisualTreeDescendants().OfType<SimpleTemplate>().Single();
var cp = contentView.GetVisualTreeDescendants().OfType<ContentPresenter>().Single();
simpleTemplate.BindingContext = bcSimpleTemplate;

Assert.Equal(bcContentView, child1.BindingContext);
Assert.Equal(contentView.BindingContext, child1.BindingContext);
Assert.Equal(bcSimpleTemplate, simpleTemplate.BindingContext);

// Change out content and make sure simple templates BC doesn't propagate
contentView.Content = child2;

Assert.Equal(bcContentView, child2.BindingContext);
Assert.Equal(contentView.BindingContext, child2.BindingContext);
Assert.Equal(bcSimpleTemplate, simpleTemplate.BindingContext);
Assert.Equal(bcSimpleTemplate, cp.BindingContext);
}

[Fact]
Expand All @@ -346,7 +376,7 @@ public void ContentDoesGetBindingContext()
}

[Fact]
public void ContentParentIsNotInsideTempalte()
public void ContentParentIsNotInsideTemplate()
{
var contentView = new ContentView();
var child = new View();
Expand Down Expand Up @@ -384,5 +414,31 @@ public void ContentView_should_have_the_InternalChildren_correctly_when_Content_
Assert.Single(internalChildren);
Assert.Same(expected, internalChildren[0]);
}


[Fact]
public void BindingContextNotLostWhenSwitchingTemplates()
{
var bc = new object();
var contentView = new ContentView()
{
BindingContext = bc
};


contentView.ControlTemplate = new ControlTemplate(typeof(SimpleTemplate));

var simpleTemplate1 = contentView.GetVisualTreeDescendants().OfType<SimpleTemplate>().Single();
contentView.Content = new Label();

Assert.Same(bc, simpleTemplate1.BindingContext);

contentView.ControlTemplate = new ControlTemplate(typeof(SimpleTemplate));

var simpleTemplate2 = contentView.GetVisualTreeDescendants().OfType<SimpleTemplate>().Single();

Assert.NotSame(simpleTemplate1, simpleTemplate2);
Assert.Same(bc, simpleTemplate2.BindingContext);
}
}
}
Loading