diff --git a/src/Controls/docs/Microsoft.Maui.Controls/ItemsView.xml b/src/Controls/docs/Microsoft.Maui.Controls/ItemsView.xml
index 6000f868b8ba..ca97036c131f 100644
--- a/src/Controls/docs/Microsoft.Maui.Controls/ItemsView.xml
+++ b/src/Controls/docs/Microsoft.Maui.Controls/ItemsView.xml
@@ -31,28 +31,6 @@
To be added.
-
-
-
-
-
- Method
-
- Microsoft.Maui.Controls.Core
- 2.0.0.0
-
-
- System.Void
-
-
-
-
-
- To be added.
- To be added.
- To be added.
-
-
@@ -530,28 +508,6 @@
To be added.
-
-
-
-
-
- Method
-
- Microsoft.Maui.Controls.Core
- 2.0.0.0
-
-
- System.Void
-
-
-
-
-
- To be added.
- To be added.
- To be added.
-
-
diff --git a/src/Controls/src/Core/Application/Application.cs b/src/Controls/src/Core/Application/Application.cs
index 7783a8403a35..53b7d3b9674d 100644
--- a/src/Controls/src/Core/Application/Application.cs
+++ b/src/Controls/src/Core/Application/Application.cs
@@ -464,7 +464,7 @@ internal void RemoveWindow(Window window)
if (window is Element windowElement)
{
- RemoveLogicalChildInternal(windowElement);
+ RemoveLogicalChild(windowElement);
}
_windows.Remove(window);
@@ -518,7 +518,7 @@ void AddWindow(Window window)
if (window is Element windowElement)
{
- AddLogicalChildInternal(windowElement);
+ AddLogicalChild(windowElement);
}
if (window is NavigableElement ne)
diff --git a/src/Controls/src/Core/BindableObject.cs b/src/Controls/src/Core/BindableObject.cs
index add82a38d079..628833ba160e 100644
--- a/src/Controls/src/Core/BindableObject.cs
+++ b/src/Controls/src/Core/BindableObject.cs
@@ -264,17 +264,12 @@ public static void SetInheritedBindingContext(BindableObject bindable, object va
protected virtual void OnBindingContextChanged()
{
BindingContextChanged?.Invoke(this, EventArgs.Empty);
+
if (Shell.GetBackButtonBehavior(this) is BackButtonBehavior buttonBehavior)
SetInheritedBindingContext(buttonBehavior, BindingContext);
if (Shell.GetSearchHandler(this) is SearchHandler searchHandler)
SetInheritedBindingContext(searchHandler, BindingContext);
-
- if (Shell.GetTitleView(this) is View titleView)
- SetInheritedBindingContext(titleView, BindingContext);
-
- if (FlyoutBase.GetContextFlyout(this) is BindableObject contextFlyout)
- SetInheritedBindingContext(contextFlyout, BindingContext);
}
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
diff --git a/src/Controls/src/Core/BindableObjectExtensions.cs b/src/Controls/src/Core/BindableObjectExtensions.cs
index 3adbbb5ed109..67be12f5ca75 100644
--- a/src/Controls/src/Core/BindableObjectExtensions.cs
+++ b/src/Controls/src/Core/BindableObjectExtensions.cs
@@ -85,6 +85,18 @@ internal static bool TrySetDynamicThemeColor(
return false;
}
+ internal static void AddRemoveLogicalChildren(this BindableObject bindable, object oldValue, object newValue)
+ {
+ if (!(bindable is Element owner))
+ return;
+
+ if (oldValue is Element oldView)
+ owner.RemoveLogicalChild(oldView);
+
+ if (newValue is Element newView)
+ owner.AddLogicalChild(newView);
+ }
+
internal static bool TrySetAppTheme(
this BindableObject self,
string lightResourceKey,
diff --git a/src/Controls/src/Core/Border/Border.cs b/src/Controls/src/Core/Border/Border.cs
index 013827e80a05..1411fe4c4636 100644
--- a/src/Controls/src/Core/Border/Border.cs
+++ b/src/Controls/src/Core/Border/Border.cs
@@ -64,8 +64,7 @@ void NotifyStrokeShapeChanges()
if (strokeShape is VisualElement visualElement)
{
- SetInheritedBindingContext(visualElement, BindingContext);
- visualElement.Parent = this;
+ AddLogicalChild(visualElement);
_strokeShapeChanged ??= (sender, e) => OnPropertyChanged(nameof(StrokeShape));
_strokeShapeProxy ??= new();
_strokeShapeProxy.Subscribe(visualElement, _strokeShapeChanged);
@@ -78,8 +77,7 @@ void StopNotifyingStrokeShapeChanges()
if (strokeShape is VisualElement visualElement)
{
- SetInheritedBindingContext(visualElement, null);
- visualElement.Parent = null;
+ RemoveLogicalChild(visualElement);
_strokeShapeProxy?.Unsubscribe();
}
}
@@ -268,12 +266,12 @@ public static void ContentChanged(BindableObject bindable, object oldValue, obje
{
if (oldValue is Element oldElement)
{
- border.RemoveLogicalChildInternal(oldElement);
+ border.RemoveLogicalChild(oldElement);
}
if (newValue is Element newElement)
{
- border.AddLogicalChildInternal(newElement);
+ border.AddLogicalChild(newElement);
}
}
diff --git a/src/Controls/src/Core/Cells/Cell.cs b/src/Controls/src/Core/Cells/Cell.cs
index 4dcaa1416d70..c63c4a94d386 100644
--- a/src/Controls/src/Core/Cells/Cell.cs
+++ b/src/Controls/src/Core/Cells/Cell.cs
@@ -243,7 +243,7 @@ public void SendDisappearing()
void IPropertyPropagationController.PropagatePropertyChanged(string propertyName)
{
- PropertyPropagationExtensions.PropagatePropertyChanged(propertyName, this, ((IElementController)this).LogicalChildren);
+ PropertyPropagationExtensions.PropagatePropertyChanged(propertyName, this, ((IVisualTreeElement)this).GetVisualChildren());
}
void OnContextActionsChanged(object sender, NotifyCollectionChangedEventArgs e)
diff --git a/src/Controls/src/Core/Cells/ViewCell.cs b/src/Controls/src/Core/Cells/ViewCell.cs
index e45ea9ba2d42..052a60d55340 100644
--- a/src/Controls/src/Core/Cells/ViewCell.cs
+++ b/src/Controls/src/Core/Cells/ViewCell.cs
@@ -23,7 +23,7 @@ public View View
if (_view != null)
{
- RemoveLogicalChildInternal(_view);
+ RemoveLogicalChild(_view);
_view.ComputedConstraint = LayoutConstraint.None;
}
@@ -32,7 +32,7 @@ public View View
if (_view != null)
{
_view.ComputedConstraint = LayoutConstraint.Fixed;
- AddLogicalChildInternal(_view);
+ AddLogicalChild(_view);
}
ForceUpdateSize();
diff --git a/src/Controls/src/Core/Compatibility/Handlers/TabbedPage/iOS/TabbedRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/TabbedPage/iOS/TabbedRenderer.cs
index 54ecabf566d1..3494df3abe9d 100644
--- a/src/Controls/src/Core/Compatibility/Handlers/TabbedPage/iOS/TabbedRenderer.cs
+++ b/src/Controls/src/Core/Compatibility/Handlers/TabbedPage/iOS/TabbedRenderer.cs
@@ -284,10 +284,10 @@ void Reset()
void SetControllers()
{
var list = new List();
- var logicalChildren = ((IElementController)Element).LogicalChildren;
- for (var i = 0; i < logicalChildren.Count; i++)
+ var pages = Tabbed.InternalChildren;
+ for (var i = 0; i < pages.Count; i++)
{
- var child = logicalChildren[i];
+ var child = pages[i];
var v = child as Page;
if (v == null)
continue;
diff --git a/src/Controls/src/Core/Element/Element.cs b/src/Controls/src/Core/Element/Element.cs
index fea1bd729e7d..e53cdf1e686c 100644
--- a/src/Controls/src/Core/Element/Element.cs
+++ b/src/Controls/src/Core/Element/Element.cs
@@ -146,7 +146,12 @@ void SetupChildren()
_logicalChildrenReadonly ??= new ReadOnlyCollection(LogicalChildrenInternalBackingStore);
}
- internal void InsertLogicalChildInternal(int index, Element element)
+ ///
+ /// Inserts an to the logical children at the specified index.
+ ///
+ /// The zero-based index at which should be inserted.
+ /// The to insert into the logical children.
+ public void InsertLogicalChild(int index, Element element)
{
if (element is null)
{
@@ -159,7 +164,11 @@ internal void InsertLogicalChildInternal(int index, Element element)
OnChildAdded(element);
}
- internal void AddLogicalChildInternal(Element element)
+ ///
+ /// Adds an to the logical children.
+ ///
+ /// The to add to the logical children.
+ public void AddLogicalChild(Element element)
{
if (element is null)
{
@@ -172,7 +181,15 @@ internal void AddLogicalChildInternal(Element element)
OnChildAdded(element);
}
- internal bool RemoveLogicalChildInternal(Element element)
+ ///
+ /// Removes the first occurrence of a specific from the logical children.
+ ///
+ /// The to remove.
+ ///
+ /// true if item was successfully removed from the logical children;
+ /// otherwise, false. This method also returns false if is not found.
+ ///
+ public bool RemoveLogicalChild(Element element)
{
if (element is null)
{
@@ -182,16 +199,19 @@ internal bool RemoveLogicalChildInternal(Element element)
if (LogicalChildrenInternalBackingStore is null)
return false;
- var oldLogicalIndex = LogicalChildrenInternalBackingStore.IndexOf(element);
- if (oldLogicalIndex < 0)
+ var index = LogicalChildrenInternalBackingStore.IndexOf(element);
+ if (index < 0)
return false;
- RemoveLogicalChildInternal(element, oldLogicalIndex);
+ RemoveLogicalChild(element, index);
return true;
}
- internal void ClearLogicalChildren()
+ ///
+ /// Removes all s.
+ ///
+ public void ClearLogicalChildren()
{
if (LogicalChildrenInternalBackingStore is null)
return;
@@ -202,41 +222,18 @@ internal void ClearLogicalChildren()
// Reverse for-loop, so children can be removed while iterating
for (int i = LogicalChildrenInternalBackingStore.Count - 1; i >= 0; i--)
{
- RemoveLogicalChildInternal(LogicalChildrenInternalBackingStore[i], i);
+ RemoveLogicalChild(LogicalChildrenInternalBackingStore[i], i);
}
}
- ///
- /// This doesn't validate that the oldLogicalIndex is correct, so be sure you're passing in the
- /// correct index
- ///
- internal bool RemoveLogicalChildInternal(Element element, int oldLogicalIndex)
+ internal bool RemoveLogicalChild(Element element, int index)
{
LogicalChildrenInternalBackingStore.Remove(element);
- OnChildRemoved(element, oldLogicalIndex);
+ OnChildRemoved(element, index);
return true;
}
- internal IEnumerable AllChildren
- {
- get
- {
- foreach (var child in LogicalChildrenInternal)
- yield return child;
-
- var childrenNotDrawnByThisElement = ChildrenNotDrawnByThisElement;
- if (childrenNotDrawnByThisElement is not null)
- {
- foreach (var child in childrenNotDrawnByThisElement)
- yield return child;
- }
- }
- }
-
- // return null by default so we don't need to foreach over an empty collection in OnPropertyChanged
- internal virtual IEnumerable ChildrenNotDrawnByThisElement => null;
-
internal bool Owned { get; set; }
internal Element ParentOverride
@@ -286,48 +283,50 @@ void IElementDefinition.AddResourcesChangedListener(Action