Skip to content

Commit

Permalink
Add ShouldAddChildrenToParent to INonPhysicalChild
Browse files Browse the repository at this point in the history
  • Loading branch information
Dreamescaper committed Aug 29, 2023
1 parent 746f597 commit 0639662
Show file tree
Hide file tree
Showing 7 changed files with 35 additions and 57 deletions.
7 changes: 7 additions & 0 deletions src/BlazorBindings.Core/INonPhysicalChild.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,11 @@ public interface INonPhysicalChild
/// This is useful so that this component can unapply its effects from parent element.
/// </summary>
void RemoveFromParent(object parentElement);

/// <summary>
/// If this property is true, then renderer will pass children of this component to parent.
/// This is useful if you want to apply some effects to children (e.g. attached properties),
/// but still add them to parent element.
/// </summary>
internal bool ShouldAddChildrenToParent { get => false; }
}
21 changes: 16 additions & 5 deletions src/BlazorBindings.Core/NativeComponentAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,8 @@ internal void ApplyEdits(int componentId, ArrayBuilderSegment<RenderTreeEdit> ed
private void ApplyRemoveFrame(int siblingIndex)
{
var childToRemove = Children[siblingIndex];
Children.RemoveAt(siblingIndex);
RemoveChildElementAndDescendants(childToRemove);
Children.RemoveAt(siblingIndex);
}

private void RemoveChildElementAndDescendants(NativeComponentAdapter childToRemove)
Expand All @@ -116,6 +116,12 @@ private void RemoveChildElementAndDescendants(NativeComponentAdapter childToRemo
// remove all descendants.
var index = PhysicalTarget.GetChildPhysicalIndex(childToRemove);
Renderer.ElementManager.RemoveChildElement(PhysicalTarget._targetElement, childToRemove._targetElement, index);

if (PhysicalTarget._targetElement is INonPhysicalChild { ShouldAddChildrenToParent: true })
{
// Since element was added to parent previosly, we have to remove it from there.
PhysicalTarget.Parent.PhysicalTarget.RemoveChildElementAndDescendants(childToRemove);
}
}
else
{
Expand Down Expand Up @@ -202,6 +208,11 @@ private void AddElementAsChildElement(NativeComponentAdapter childAdapter)
{
var elementIndex = PhysicalTarget.GetChildPhysicalIndex(childAdapter);
Renderer.ElementManager.AddChildElement(PhysicalTarget._targetElement, childAdapter._targetElement, elementIndex);

if (PhysicalTarget._targetElement is INonPhysicalChild { ShouldAddChildrenToParent: true })
{
PhysicalTarget.Parent.AddElementAsChildElement(childAdapter);
}
}

/// <summary>
Expand Down Expand Up @@ -235,12 +246,12 @@ static bool FindChildPhysicalIndexRecursive(NativeComponentAdapter parent, Nativ
if (child == targetChild)
return true;

if (child._targetElement != null)
if (child._targetElement != null && child._targetElement is not INonPhysicalChild)
{
if (child._targetElement is not INonPhysicalChild)
index++;
index++;
}
else

if (child._targetElement == null || child._targetElement is INonPhysicalChild { ShouldAddChildrenToParent: true })
{
if (FindChildPhysicalIndexRecursive(child, targetChild, ref index))
return true;
Expand Down
3 changes: 2 additions & 1 deletion src/BlazorBindings.Core/Properties/AttributeInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@

using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("BlazorBindings.UnitTests")]
[assembly: InternalsVisibleTo("BlazorBindings.UnitTests")]
[assembly: InternalsVisibleTo("BlazorBindings.Maui")]
47 changes: 7 additions & 40 deletions src/BlazorBindings.Maui/Elements/GridCell.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

using BlazorBindings.Maui.Extensions;
using MC = Microsoft.Maui.Controls;

namespace BlazorBindings.Maui.Elements;
Expand All @@ -16,9 +17,6 @@ public class GridCell : NativeControlComponentBase, IContainerElementHandler, IN


private readonly List<MC.View> _children = new();
private MC.Grid _parentGrid;

object IElementHandler.TargetElement => null;

public override Task SetParametersAsync(ParameterView parameters)
{
Expand Down Expand Up @@ -73,55 +71,24 @@ public override Task SetParametersAsync(ParameterView parameters)

public void AddChild(object child, int physicalSiblingIndex)
{
if (child is not MC.View childView)
{
throw new ArgumentException($"Expected parent to be of type {typeof(MC.View).FullName} but it is of type {child?.GetType().FullName}.", nameof(child));
}
var childView = child.Cast<MC.View>();

MC.Grid.SetColumn(childView, Column ?? 0);
MC.Grid.SetColumnSpan(childView, ColumnSpan ?? 1);
MC.Grid.SetRow(childView, Row ?? 0);
MC.Grid.SetRowSpan(childView, RowSpan ?? 1);

_children.Add(childView);
_parentGrid.Children.Add(childView);
}

public void RemoveChild(object child, int physicalSiblingIndex)
{
if (child is not MC.View childView)
{
throw new ArgumentException($"Expected parent to be of type {typeof(MC.View).FullName} but it is of type {child?.GetType().FullName}.", nameof(child));
}

var childView = child.Cast<MC.View>();
_children.Remove(childView);
_parentGrid.Children.Remove(childView);
}

public int GetChildIndex(object child)
{
return child is MC.View childView
? _children.IndexOf(childView)
: -1;
}

void INonPhysicalChild.SetParent(object parentElement)
{
_parentGrid = parentElement as MC.Grid
?? throw new ArgumentException($"Expected parent to be of type {typeof(MC.Grid).FullName} but it is of type {parentElement?.GetType().FullName}.", nameof(parentElement));
}

void INonPhysicalChild.RemoveFromParent(object parentElement)
{
if (_parentGrid != null)
{
foreach (var child in _children)
{
_parentGrid.Children.Remove(child);
}

_children.Clear();
_parentGrid = null;
}
}
object IElementHandler.TargetElement => null;
void INonPhysicalChild.SetParent(object parentElement) { }
void INonPhysicalChild.RemoveFromParent(object parentElement) { }
bool INonPhysicalChild.ShouldAddChildrenToParent => true;
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,6 @@ public void AddChild(object child, int physicalSiblingIndex)
_application.MainPage = child.Cast<MC.Page>();
}

public int GetChildIndex(object child)
{
return Equals(_application.MainPage, child) ? 0 : -1;
}

public void RemoveChild(object child, int physicalSiblingIndex)
{
// It is not allowed to have no MainPage.
Expand Down
2 changes: 0 additions & 2 deletions src/BlazorBindings.Maui/Navigation/NavigationHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,5 @@ public async void AddChild(object child, int physicalSiblingIndex)
await AddChildAsync((MC.Page)child);
}

public int GetChildIndex(object child) => -1;
public object ElementControl => null;
public object TargetElement => null;
}
7 changes: 3 additions & 4 deletions src/BlazorBindings.UnitTests/Elements/GridTests.razor
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,7 @@
</Grid>
);

// Order of children doesn't really matter for Grid.
var labels = grid.Children.Cast<MC.Label>().OrderBy(l => l.Text).ToArray();
var labels = grid.Children.Cast<MC.Label>().ToArray();
var label00a = labels[0];
var label00b = labels[1];
var label01a = labels[2];
Expand Down Expand Up @@ -172,7 +171,7 @@
insertItems = false;
StateHasChanged();

labels = grid.Children.Cast<MC.Label>().OrderBy(l => l.Text).ToArray();
labels = grid.Children.Cast<MC.Label>().ToArray();
label00b = labels[0];
label01a = labels[1];
label10a = labels[2];
Expand All @@ -193,7 +192,7 @@
insertItems = true;
StateHasChanged();

labels = grid.Children.Cast<MC.Label>().OrderBy(l => l.Text).ToArray();
labels = grid.Children.Cast<MC.Label>().ToArray();
label00a = labels[0];
label00b = labels[1];
label01a = labels[2];
Expand Down

0 comments on commit 0639662

Please sign in to comment.