Click here to Skip to main content
15,868,016 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I'm new to Xamarin Forms, most of my experience is with Windows Forms and C#. The project I'm trying make has a DataGrid using Xamarin.Forms.DataGrid, and a button to use for updating the data and refreshing the DataGrid.
The project is based on example code I found at
https://www.c-sharpcorner.com/article/xamarin-forms-datagrid/
The app runs okay on an Android phone, displaying the default test data.

I want to be able to update the DataGrid using new data calculated in C# 'Code Behind' (based on date/time and some user input), but I can't figure out how to do it. The UPDATE button click fires an event handler "UpdateGrid" in the MainPage.xaml.cs file. I can see it being called in debug. What do I need to put in this event handler to update the DataGrid with the new data?

On startup an object of MainPageViewModel() is assigned to 'BindingContext' (don't understand the detail). That object contains 'TestData' of type List<rowdata> and it has the default data that is displayed correctly.

Here are the contents of MainPage.xaml, MainPage.xaml.cs, MainPageViewModel.cs -

XML
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"  
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"  
             xmlns:dg="clr-namespace:Xamarin.Forms.DataGrid;assembly=Xamarin.Forms.DataGrid"
             x:Class="XForms1.MainPage">
    <ContentView>
        <StackLayout Orientation="Vertical" Padding="30,24,30,24" Spacing="10" HorizontalOptions="FillAndExpand">

            <Button Text="Update" Clicked="UpdateGrid" />

            <dg:DataGrid x:Name="datagrid1" ItemsSource="{Binding TestData}" SelectionEnabled="True"
                         SelectedItem="{Binding RowData}" RowHeight="40" HeaderHeight="50" BorderColor="#CCCCCC"
                         HeaderBackground="#E0E6F8" PullToRefreshCommand="{Binding RefreshCommand}"
                         IsRefreshing="{Binding IsRefreshing}" ActiveRowColor="#8899AA">
                <x:Arguments>
                    <ListViewCachingStrategy>RetainElement</ListViewCachingStrategy>
                </x:Arguments>

                <dg:DataGrid.HeaderFontSize>
                    <OnIdiom x:TypeArguments="x:Double">
                        <OnIdiom.Tablet>15</OnIdiom.Tablet>
                        <OnIdiom.Phone>12</OnIdiom.Phone>
                    </OnIdiom>
                </dg:DataGrid.HeaderFontSize>

                <dg:DataGrid.Columns>
                    <dg:DataGridColumn Title="Col 1" PropertyName="Str1" Width="1*"/>
                    <dg:DataGridColumn Title="Col 2" PropertyName="Str2" Width="1*"/>
                    <dg:DataGridColumn Title="Col 3" PropertyName="Str3" Width="1*"/>
                    <dg:DataGridColumn Title="Col 4" PropertyName="Str4" Width="1*"/>
                </dg:DataGrid.Columns>

                <dg:DataGrid.RowsBackgroundColorPalette>
                    <dg:PaletteCollection>
                        <Color>#F2F2F2</Color>
                        <Color>#FFFFFF</Color>
                    </dg:PaletteCollection>
                </dg:DataGrid.RowsBackgroundColorPalette>

            </dg:DataGrid>
        </StackLayout>
    </ContentView>
</ContentPage>

*************** MainPage.xaml.cs **************
C#
using System;
using Xamarin.Forms;
using XForms1.ViewModels;
using static XForms1.Utils.MyTestData;

namespace XForms1
{
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
            BindingContext = new MainPageViewModel();
        }
        private void UpdateGrid(object sender, EventArgs e) 
        {
            // tried the following, but it doesn't do anything. What do I need to put here?
            datagrid1.BindingContext = GetTestData2();            
        }
    }
}

*************** MainPageViewModel.cs **************
C#
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading.Tasks;
using System.Windows.Input;
using Xamarin.Forms;
using XForms1.Models;
using XForms1.Utils;

namespace XForms1.ViewModels
{
    public class MainPageViewModel : INotifyPropertyChanged
    {
        private List<RowData> _testdata;
        private RowData _rowdata;
        private bool _isRefreshing;

        public MainPageViewModel()
        {
            TestData = MyTestData.GetTestData();
            RefreshCommand = new Command(CmdRefresh);
        }
        public List<RowData> TestData
        {
            get => _testdata;
            set {_testdata = value; OnPropertyChanged(nameof(TestData));}              
        }
        public RowData SelectedRow
        {
            get => _rowdata;
            set{ _rowdata = value; OnPropertyChanged(nameof(SelectedRow)); }
        }

        public bool IsRefreshing
        {
            get => _isRefreshing;
            set { _isRefreshing = value; OnPropertyChanged(nameof(IsRefreshing)); }        
        }

        public ICommand RefreshCommand { get; set; }

        private async void CmdRefresh()
        {
            IsRefreshing = true;
            await Task.Delay(3000);
            IsRefreshing = false;
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string property)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(property));
        }
    }
}

Any help would be greatly appreciated!

What I have tried:

I have searched the internet for an answer. I must be missing some basic principal because Xamarin Forms is supposed to handle data binding and refreshing easily.
The example code I used may not be suited to what I'm trying to do.
Posted
Updated 6-Oct-21 4:44am

1 solution

Since the time I posted this question I have found a suitable solution. I found a different example that used ListView instead of DataGrid. While I really needed DataGrid, I thought I might be able to use the same technique since the ListView example worked.

The new example uses
ObservableCollection<type>
as the data source instead of
List<type>
and it is created in MainPage.xaml.cs code behind, not in the separate MainPageViewModel class which implemented
INotifyPropertyChanged
Having the data source accessible from MainPage code made it possible for me to modify it in an event handler, and since it was of type ObservableCollection, and bound to the DataGrid, the DataGrid was automatically refreshed. There were other details of how to set the binding -
<dg:DataGrid x:Name="MyStars" ItemsSource="{Binding Source={x:Reference ContentPage1}, Path=BindingContext.StarList etc-etc.}">

Sorry if I'm not using the correct terminology, but as I said, I'm completely new to Xamarin and programming for mobile devices. I'm still very much in the monkey-see-monkey-do mode.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900