Any component deriving from RxComponent
can render anything in its Render()
overload.
Sometimes is useful a component that arranges children.
Say we want for example to create a component that arranges its children within a customizable grid, like this:
To start let's create a component that build our page:
public class PageComponent : RxComponent
{
public override VisualNode Render()
{
return new RxNavigationPage()
{
new RxContentPage()
{
}
.Title("Component With Children")
};
}
}
This should show a page with a title; let's now create a component for our grid (call it WrapGrid
)
public class WrapGrid : RxComponent
{
public override VisualNode Render()
{
}
}
Every RxComponent
can access its children using Children() method (like {this.props.children}
in react)
public class WrapGrid : RxComponent
{
public override VisualNode Render()
{
return new RxGrid()
{
Children().ToArray()
};
}
}
Now let's add a ColumnCount
property and a simple logic to arrange and wraps any children passed
public class WrapGrid : RxComponent
{
private int _columnCount = 4;
public WrapGrid ColumnCount(int columnCount)
{
_columnCount = columnCount;
return this;
}
public override VisualNode Render()
{
int rowIndex = 0, colIndex = 0;
int rowCount = Math.DivRem(Children().Count, _columnCount, out var divRes);
if (divRes > 0)
rowCount++;
return new RxGrid(
Enumerable.Range(1, rowCount).Select(_ => new RowDefinition() { Height = GridLength.Auto }),
Enumerable.Range(1, _columnCount).Select(_ => new ColumnDefinition()))
{
Children().Select(child =>
{
child.GridRow(rowIndex);
child.GridColumn(colIndex);
colIndex++;
if (colIndex == _columnCount)
{
colIndex = 0;
rowIndex++;
}
return child;
}).ToArray()
};
}
}
Finally we just need to create the component from the page:
public class PageState : IState
{
public int ColumnCount { get; set; } = 1;
public int ItemCount { get; set; } = 3;
}
public class PageComponent : RxComponent<PageState>
{
public override VisualNode Render()
{
return new RxNavigationPage()
{
new RxContentPage()
{
new RxStackLayout()
{
new RxLabel($"Columns {State.ColumnCount}")
.FontSize(Xamarin.Forms.NamedSize.Large),
new RxStepper()
.Minimum(1)
.Maximum(10)
.Increment(1)
.Value(State.ColumnCount)
.OnValueChanged(_=> SetState(s => s.ColumnCount = (int)_.NewValue)),
new RxLabel($"Items {State.ItemCount}")
.FontSize(Xamarin.Forms.NamedSize.Large),
new RxStepper()
.Minimum(1)
.Maximum(20)
.Increment(1)
.Value(State.ItemCount)
.OnValueChanged(_=> SetState(s => s.ItemCount = (int)_.NewValue)),
new WrapGrid()
{
Enumerable.Range(1, State.ItemCount)
.Select(_=> new RxButton($"Item {_}"))
.ToArray()
}
.ColumnCount(State.ColumnCount)
}
.Padding(10)
.WithVerticalOrientation()
}
.Title("Component With Children")
};
}
}