0
votes

Say I have a list of items displayed as a Grid layout. Each item takes up a row and is made up of multiple items in a column. It's basically a table:

<Grid>
 <Label Text="Item1" Grid.Row="0" Grid.Colum="0" />
 <Image Src="something1" Grid.Row="0" Grid.Colum="1" />

 <Label Text="Item2" Grid.Row="1" Grid.Colum="0" />
 <Image Src="something2" Grid.Row="1" Grid.Colum="1" />

 <Label Text="Item3" Grid.Row="2" Grid.Colum="0" />
 <Image Src="something3" Grid.Row="2" Grid.Colum="1" />
</Grid>

Each Label/Image represents a row in my list of items to be displayed. I'm not worried about the databinding for the moment, I just want to move the Label/Image into a custom control so that I can use that custom control to add "Rows" into my Grid:

<Grid>
 <customcontrol:MyCustomRowControl Text="Item1" Source="img1" Grid.Row="0"/>
 <customcontrol:MyCustomRowControl Text="Item2" Source="img1" Grid.Row="1"/>
 <customcontrol:MyCustomRowControl Text="Item3" Source="img1" Grid.Row="3"/>
</Grid>

I can probably set the Lable/Image/etc from my custom control to it's appropriate row/column from the code-behind.Where I get lost is what type of base class should I make this custom control? Because it is that class that will become the content of the Grid, not it's Labels and Images, therefore the Grid.Row and Grid.Column will not propagate correctly. I really hope I managed to explain this.

Can I create a custom control in Xamarin that I can add as a content to a Grid and have it's children respect the Grid's columns?

1
If I understand this right, you can make it a Grid with two columns, column 0 is Label and column 1 is Image. Then use customcontrol with ColumnSpan=2 - Dennis Schröer
Well, yeah that will compile, but the columns will not be equalized between items. Each Label will have it's own width, so the table will essentially be broken - Radu094
Do you want all Labels to have the width of the widest Label? Otherwise you could work with fixed widths (* instead of Auto in ColumnDefinitions) - Dennis Schröer
Yeah, I have some columns there on Auto , and I want those column widths to propagate on all rows, essentially creating a table - Radu094
Can you able to test my code? @Radu094 - Batuhan

1 Answers

0
votes

You can write about like this

DynamicGridView class

public class DynamicGridView : Grid
{
        private int _rowCount;
        private int _columnCount;
        protected int _column;
        protected int _starHeight = 0;
        protected int _type;
        protected int[] _starHeightList;

        public DynamicGridEnum _dynamicGridEnum;

        public DynamicGridView(DynamicGridEnum dynamicGridEnum, params int[] starHeightList)
        {
            _type = 2;
            switch (dynamicGridEnum)
            {
                case DynamicGridEnum.Auto:
                    _column = starHeightList[0];
                    break;
                case DynamicGridEnum.Star:
                    _column = starHeightList[0];
                    _starHeight = starHeightList[1];
                    _type = 1;
                    break;
                case DynamicGridEnum.Custom:
                    _column = starHeightList.Length;
                    break;
                default:
                    break;
            }
            _starHeightList = starHeightList;
            _dynamicGridEnum = dynamicGridEnum;
            _rowCount = 0;
            _columnCount = 0;
            Padding = 0;
            Margin = 0;
            ColumnSpacing = -1;
            RowSpacing = -1;
        }

        public virtual void AddView(View view)
        {
            int countRow = _rowCount / _column;
            if (RowDefinitions.Count <= countRow)
            {
                RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, (GridUnitType)_type) });
            }
            Children.Add(view, _columnCount, countRow);
            _rowCount++;
            _columnCount++;
            _columnCount = _columnCount % _column;
        }
}

DynamicGrid class

public class DynamicGrid : DynamicGridView
{
        public DynamicGrid(DynamicGridEnum dynamicGridEnum, params int[] starHeightList) : base(dynamicGridEnum, starHeightList)
        {
            for (int i = 0; i < starHeightList.Length; i++) { starHeightList[i] = starHeightList[i] <= 0 ? 1 : starHeightList[i]; }

            if (dynamicGridEnum == DynamicGridEnum.Custom)
            {
                StartCustomGrid();
            }
            else
                StartGrid();
        }

        private void StartGrid()
        {
            int percent = 100 / _column;
            for (int i = 0; i < _column; i++)
                ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(percent, (GridUnitType)_type) });
        }

        private void StartCustomGrid()
        {
            foreach (var item in _starHeightList)
                ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(item, GridUnitType.Star) });
        }
}

And usage of dynamic grid (I defined an enum for type of grid. For example if enum is auto it will be auto resize row/columns of grid.)

public partial class MainPage : ContentPage
{
public MainPage()
{
   StackLayout sl = new StackLayout();
   DynamicGrid dynamicGrid = new DynamicGrid(Enums.DynamicGridEnum.Custom, 20, 50, 20, 0);
   dynamicGrid.AddView(new BoxView() { BackgroundColor = Color.AliceBlue });
   dynamicGrid.AddView(new BoxView() { BackgroundColor = Color.Aqua });
   dynamicGrid.AddView(new BoxView() { BackgroundColor = Color.AntiqueWhite });
   dynamicGrid.AddView(new BoxView() { BackgroundColor = Color.Azure });
   sl.Children.Add(new CardView(Color.Beige, Color.Bisque, 60, Color.Black, 90, 10));
   sl.Children.Add(dynamicGrid);
   Content = sl;
}
}