Forum Xamarin.Forms

Announcement:

The Xamarin Forums have officially moved to the new Microsoft Q&A experience. Microsoft Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

To create new threads and ask questions head over to Microsoft Q&A for .NET and get involved today.

Dynamically load grid columns and rows from database values.

Hi there
I have some data in a database with a number of columns and rows. I want to be able to generate a grid using this data.

I have a View (I am creating it in c# as opposed to xaml as I thought this made sense given I wanted it to be dynamic).
I then have a ViewModel which loads the data with a command. This is put into a Model that has two integers one for the columns and rows.

I did some initial testing and created the grid using hardcoded values to make sure the gird drew as expected etc.

The issue is when loading from a command the Model values are not populated until after the screen has been drawn. So the values are 0.

Is there a Command complete or similar event I can hook into?
Do I need to create an event on the view model to hook into to draw the grid?

Here is an example of some of my code:

VIEW:
public partial class DynamicGridView : ContentPage
{
DynamicGridViewModel DynamicGridVM { get; set; }

    public DynamicGridView(InputModel model)
    {
        InitializeComponent();
        DynamicGridVM = new DynamicGridViewModel(model);
        BindingContext = DynamicGridVM;

        DynamicGridVM.LoadGridDataCmd.Execute(null);

    Grid grid = new Grid();

        int rows = 22;
        int columns = 18;

           RowDefinitionCollection rowDefinitions = new RowDefinitionCollection();
            ColumnDefinitionCollection columnDefinitions = new ColumnDefinitionCollection();

            for (int i = 0; i < rows; i++)
            {
                rowDefinitions.Add(new RowDefinition() { Height = GridLength.Star });
            }

            for (int i = 0; i < columns; i++)
            {
                columnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Star });
            }

            grid.RowDefinitions = rowDefinitions;
            grid.ColumnDefinitions = columnDefinitions;
            grid.Margin = 1;
            grid.Padding = 1;
            grid.ColumnSpacing = 1;
            grid.RowSpacing = 1;
            grid.BackgroundColor = Color.FromHex("55FFFFFF");

for (int i = 0; i < rows; i++)
{
for (int j = 0; j < columns; j++)
{
BoxView newCell = new BoxView();
grid.Children.Add(newCell, i, j);
}
}

AbsoluteLayout.SetLayoutBounds(grid, new Rectangle(0.5, 0.2, 500, 250));
AbsoluteLayout.SetLayoutFlags(grid, AbsoluteLayoutFlags.PositionProportional);

Content = new AbsoluteLayout
{
Children = { grid }
};

}

}

**
VIEW MODEL**
public DynamicModel Model { get; set; }

    public  DynamicGridViewModel(InputModel model)
    {
        Model = new DynamicModel(model);
    }

    public ICommand LoadGridDataCmd
    {
        get
        {
            return new Command(async () => await LoadGridData());
        }
    }

private async Task LoadGridData()
{
Model.Rows = 20;
Model.Rows = 10;
}

The model just has the int for the row and column number.

The issue seems to be the View calls DynamicGridVM.LoadGridDataCmd.Execute(null); This is called with an async method.
The view details are then called.

If I set the rows and columns in the view to:
** int rows = DynamicGridVM.Model.Rows;
int columns = DynamicGridVM.Model.Columns;**

They are 0 upon the initial load.
I have put some debug and alerts in the app and can confirm the the values from the model should be 20 and 10. (To be loaded from an external source).

At this point the view has already been created and the grid will have no rows.

I'm not sure if there is a way to do this in XAML with some bindings?

Maybe there is an event I can hook into that I can then add more rows/columns to the grid when the Command has executed?

Any help or insights would be greatly appreciated
Thanks

Best Answer

  • ColeXColeX Member, Xamarin Team Xamurai
    edited February 4 Accepted Answer

    You can await the asynchronous method in OnAppearing method .

    Construct the Grid according to the data from database .

    Sample code

    public class DynamicModel
        {
            public int column;
            public int row;
        }
        public class DynamicGridViewModel
        {
    
    
            public DynamicGridViewModel()
            {
    
            }
    
            public ICommand LoadGridDataCmd
            {
                get
                {
                    return new Command(async () => await LoadGridData());
                }
            }
    
    
            public async Task<DynamicModel> LoadGridData()
            {
                await Task.Delay(5000);
    
                /// get data from database 
                DynamicModel model = new DynamicModel { row = 5, column = 6 };
    
                return model;
            }
        }
    
    //page
    
     Grid grid = null;
            protected async override void OnAppearing()
            {
                base.OnAppearing();
    
    
                if (grid == null){
                    DynamicGridViewModel model = new DynamicGridViewModel();
    
                    var m = await model.LoadGridData();
    
    
                    Grid grid = new Grid();
    
                    int rows = m.row;
                    int columns = m.column;
    
                    RowDefinitionCollection rowDefinitions = new RowDefinitionCollection();
                    ColumnDefinitionCollection columnDefinitions = new ColumnDefinitionCollection();
    
                    for (int i = 0; i < rows; i++)
                    {
                        rowDefinitions.Add(new RowDefinition() { Height = GridLength.Star });
                    }
    
                    for (int i = 0; i < columns; i++)
                    {
                        columnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Star });
                    }
    
                    grid.RowDefinitions = rowDefinitions;
                    grid.ColumnDefinitions = columnDefinitions;
                    grid.Margin = 1;
                    grid.Padding = 1;
                    grid.ColumnSpacing = 1;
                    grid.RowSpacing = 1;
                    grid.BackgroundColor = Color.FromHex("55FFFFFF");
    
                    for (int i = 0; i < rows; i++)
                    {
                        for (int j = 0; j < columns; j++)
                        {
                            Label newCell = new Label();
                            newCell.BackgroundColor = Color.Red;
                            newCell.Text = i.ToString() + "-" + j.ToString();
                            grid.Children.Add(newCell, i, j);
                        }
                    }
    
                    Content = grid;
                }     
            }
    

    Xamarin forums are migrating to a new home on Microsoft Q&A!
    We invite you to post new questions in the Xamarin forums’ new home on Microsoft Q&A!
    For more information, please refer to this sticky post.

Answers

  • ColeXColeX Member, Xamarin Team Xamurai
    edited February 4 Accepted Answer

    You can await the asynchronous method in OnAppearing method .

    Construct the Grid according to the data from database .

    Sample code

    public class DynamicModel
        {
            public int column;
            public int row;
        }
        public class DynamicGridViewModel
        {
    
    
            public DynamicGridViewModel()
            {
    
            }
    
            public ICommand LoadGridDataCmd
            {
                get
                {
                    return new Command(async () => await LoadGridData());
                }
            }
    
    
            public async Task<DynamicModel> LoadGridData()
            {
                await Task.Delay(5000);
    
                /// get data from database 
                DynamicModel model = new DynamicModel { row = 5, column = 6 };
    
                return model;
            }
        }
    
    //page
    
     Grid grid = null;
            protected async override void OnAppearing()
            {
                base.OnAppearing();
    
    
                if (grid == null){
                    DynamicGridViewModel model = new DynamicGridViewModel();
    
                    var m = await model.LoadGridData();
    
    
                    Grid grid = new Grid();
    
                    int rows = m.row;
                    int columns = m.column;
    
                    RowDefinitionCollection rowDefinitions = new RowDefinitionCollection();
                    ColumnDefinitionCollection columnDefinitions = new ColumnDefinitionCollection();
    
                    for (int i = 0; i < rows; i++)
                    {
                        rowDefinitions.Add(new RowDefinition() { Height = GridLength.Star });
                    }
    
                    for (int i = 0; i < columns; i++)
                    {
                        columnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Star });
                    }
    
                    grid.RowDefinitions = rowDefinitions;
                    grid.ColumnDefinitions = columnDefinitions;
                    grid.Margin = 1;
                    grid.Padding = 1;
                    grid.ColumnSpacing = 1;
                    grid.RowSpacing = 1;
                    grid.BackgroundColor = Color.FromHex("55FFFFFF");
    
                    for (int i = 0; i < rows; i++)
                    {
                        for (int j = 0; j < columns; j++)
                        {
                            Label newCell = new Label();
                            newCell.BackgroundColor = Color.Red;
                            newCell.Text = i.ToString() + "-" + j.ToString();
                            grid.Children.Add(newCell, i, j);
                        }
                    }
    
                    Content = grid;
                }     
            }
    

    Xamarin forums are migrating to a new home on Microsoft Q&A!
    We invite you to post new questions in the Xamarin forums’ new home on Microsoft Q&A!
    For more information, please refer to this sticky post.

  • Philip_orrillPhilip_orrill Member ✭✭

    Thank you very much.
    I have updated the loading to be in the onappearing and it is exactly what I wanted.

Sign In or Register to comment.