title: Xamarin Firebase and Syncfusion DataGrid. How do I listen for Firebase changes?
body: <p>I'm having trouble with the coding to properly listen for Firebase add or update events.  My attempt below has the data loading into the Syncfusion Datagrid, but there is a weird glitch where when I click the mouse on the Datagrid and pull-down, the first record in my 4 record set gets added to the bottom of the Datagrid, showing a 5th record... if I update an element in the Datagrid, the change is not reflected in Firebase. If I add or change a value in firebase, it does not update in Datagrid.  Any help to steer me in the right direction to get this to work would be appreciated.  Here's the code:</p>
  
  <p>the VisualStudio 2019 </p>
  
  <p><strong>CookPage.xaml</strong></p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8" ?&gt;
  &lt;ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
               xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
               xmlns:d="http://xamarin.com/schemas/2014/forms/design"
               xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
               xmlns:local="clr-namespace:Chart_sample"
               xmlns:gauge="clr-namespace:Syncfusion.SfGauge.XForms;assembly=Syncfusion.SfGauge.XForms"
               xmlns:Syncfusion="clr-namespace:Syncfusion.SfDataGrid.XForms;assembly=Syncfusion.SfDataGrid.XForms"
               mc:Ignorable="d"
               x:Class="Chart_sample.Views.CookPage"&gt;
      &lt;StackLayout&gt;
          &lt;Syncfusion:SfDataGrid x:Name="sfGrid"&gt;
          &lt;/Syncfusion:SfDataGrid&gt;
      &lt;/StackLayout&gt;
  &lt;/ContentPage&gt;
  </code></pre>
  
  <p><strong>CookPage.xaml.cs</strong></p>
  
  <pre><code>using Chart_sample.Services;
  using Syncfusion.SfDataGrid.XForms;
  using Xamarin.Forms;
  using Xamarin.Forms.Xaml;
  
  namespace Chart_sample.Views
  {
      [XamlCompilation(XamlCompilationOptions.Compile)]
      public partial class CookPage : ContentPage
      {
          FirebaseHelper firebaseHelper = new FirebaseHelper();
          public CookPage()
          {
              InitializeComponent();
  
              // for Syncfusion DataGrid 
              firebaseHelper.listenForEvents();
              sfGrid.ItemsSource = ViewProgramModel._returnedEvents;
              sfGrid.ColumnSizer = ColumnSizer.Star;
              sfGrid.AllowEditing = true;
              sfGrid.NavigationMode = NavigationMode.Cell;
              sfGrid.SelectionMode = Syncfusion.SfDataGrid.XForms.SelectionMode.Single;
          }
      }
  }
  </code></pre>
  
  <p><strong>FirebaseHelper.cs</strong></p>
  
  <pre><code>using Firebase.Database;
  using Firebase.Database.Query;
  using System;
  using System.Linq;
  
  namespace Chart_sample.Services
  {
      public class FirebaseHelper
      {
  
          internal ViewProgramModel ViewProgramModel { get; set; }
          FirebaseClient firebase = new FirebaseClient("https://pelletpirate.firebaseio.com/");
          private readonly string ChildProgram = "ControllerData/Pellet_Pirate_1/Program";
          public static IDisposable returnedEvents;
  
          public async void listenForEvents()
          {
              ViewProgramModel._returnedEvents.Clear();
  
              var programs = await firebase.Child(ChildProgram).OnceAsync&lt;ViewProgramModel&gt;();
              for (int i = 0; i &lt; programs.Count; i++)
              {
                  ViewProgramModel._returnedEvents.Add(programs.ElementAt(i).Object);
              }
  
              returnedEvents = firebase.Child(ChildProgram).OrderByKey().AsObservable&lt;ViewProgramModel&gt;()
                  .Subscribe(eventReceived =&gt;
                  {
                  if (eventReceived.EventType == Firebase.Database.Streaming.FirebaseEventType.InsertOrUpdate)
                  {
  
                      var found = ViewProgramModel._returnedEvents.FirstOrDefault(i =&gt; i._KEY == eventReceived.Key);
  
                      if (found == null)
                      {
                          // not in observable collection, add it
                          ViewProgramModel._returnedEvents.Add(eventReceived.Object);
                      }
                      else
                      {
                          // event was updated
                          int tempIndex = ViewProgramModel._returnedEvents.IndexOf(found);
                          ViewProgramModel._returnedEvents[tempIndex] = eventReceived.Object;
                      }
                  }
              });
          }
      }
  }
  </code></pre>
  
  <p><strong>ViewProgrammodel.cs</strong></p>
  
  <pre><code>using System.Collections.ObjectModel;
  using System.ComponentModel;
  
  namespace Chart_sample
  {
      public class ViewProgramModel : INotifyPropertyChanged
      {
  
          public event PropertyChangedEventHandler PropertyChanged;
  
          private string _KEy;
          private string MOde;
          private int TArget;
          private string TRigger;
          private int TRiggerVAlue;
  
  
          public string _KEY
          {
              get { return _KEy; }
              set
              {
                  this._KEy = value;
                  PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("_KEY"));
              }
          }
  
          public string MODE
          {
              get { return MOde; }
              set
              {
                  this.MOde = value;
                  PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("MODE"));
              }
          }
  
          public int TARGET
          {
              get { return TArget; }
              set
              {
                  this.TArget = value;
                  PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("TARGET"));
              }
          }
  
          public string TRIGGER
          {
              get { return TRigger; }
              set
              {
                  this.TRigger = value;
                  PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("TRIGGER"));
              }
          }
  
          public int TRIGGERVALUE
          {
              get { return TRiggerVAlue; }
              set
              {
                  this.TRiggerVAlue = value;
                  PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("TRIGGERVALUE"));
              }
          }
  
          public static ObservableCollection&lt;ViewProgramModel&gt; _returnedEvents = new ObservableCollection&lt;ViewProgramModel&gt;();
      }
  }
  </code></pre>