Xamarin Firebase и Syncfusion DataGrid. Как мне прослушать изменения в Firebase? - PullRequest
0 голосов
/ 14 апреля 2020

У меня проблемы с кодировкой для правильного прослушивания событий добавления или обновления Firebase. Моя попытка ниже - загрузка данных в Syncfusion Datagrid, но есть странный сбой, когда при щелчке мышью по Datagrid и выпадающем меню первая запись в моем наборе из 4 записей добавляется в нижнюю часть Datagrid, показывая 5-я запись ... если я обновлю элемент в Datagrid, изменение не будет отражено в Firebase. Если я добавляю или изменяю значение в firebase, оно не обновляется в Datagrid. Буду признателен за любую помощь, чтобы направить меня в правильном направлении, чтобы заставить это работать. Вот код:

VisualStudio 2019

CookPage.xaml

<?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: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">
    <StackLayout>
        <Syncfusion:SfDataGrid x:Name="sfGrid">
        </Syncfusion:SfDataGrid>
    </StackLayout>
</ContentPage>

CookPage.xaml.cs

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;
        }
    }
}

FirebaseHelper.cs

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<ViewProgramModel>();
            for (int i = 0; i < programs.Count; i++)
            {
                ViewProgramModel._returnedEvents.Add(programs.ElementAt(i).Object);
            }

            returnedEvents = firebase.Child(ChildProgram).OrderByKey().AsObservable<ViewProgramModel>()
                .Subscribe(eventReceived =>
                {
                if (eventReceived.EventType == Firebase.Database.Streaming.FirebaseEventType.InsertOrUpdate)
                {

                    var found = ViewProgramModel._returnedEvents.FirstOrDefault(i => 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;
                    }
                }
            });
        }
    }
}

ViewProgrammodel.cs

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<ViewProgramModel> _returnedEvents = new ObservableCollection<ViewProgramModel>();
    }
}

1 Ответ

1 голос
/ 14 апреля 2020

Я редактирую ваше демо, я достигаю обновления, добавления, удаления функции.

Здесь работает GIF.

enter image description here

Я изменяю ваш ViewProgramModel как следующий код. Просто переместите _returnedEvents в FirebaseHelper.cs

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"));
            }
        }
    }

Вот FirebaseHelper.cs, Примечание: я получаю функцию обновления только для столбца TARGET, я предлагаю вам добавить первичный ключ (Авто-увеличение) для каждой записи в вашей базе данных для достижения вашей функции поиска.

    public class FirebaseHelper
    {
        public ObservableCollection<ViewProgramModel> _returnedEvents { get; set; }
        public FirebaseHelper()
        {
            _returnedEvents = new ObservableCollection<ViewProgramModel>();
         }

      //  internal ViewProgramModel MyViewProgramModel { get; set; }
        FirebaseClient firebase = new FirebaseClient("https://xxxxxxxxxx.firebaseio.com/");
        private readonly string ChildProgram = "ControllerData/xxxxxx_Pirate_1/Program";
        public static IDisposable returnedEvents;
        public async Task AddViewProgramModel()
        {
            //new ViewProgramModel() { MODE="test", TARGET=122, TRIGGER="122", TRIGGERVALUE=333,  }
            await firebase
              .Child(ChildProgram)
              .PostAsync( new ViewProgramModel() { MODE = "test", TARGET = 122, TRIGGER = "122", TRIGGERVALUE = 333, });
            GetAllData();
        }

        public async Task UpdateViewProgramModel(ViewProgramModel viewProgramModel , string oldValue)
        {
            var toUpdatePerson = (await firebase
                .Child(ChildProgram)
                .OnceAsync<ViewProgramModel>()).FirstOrDefault(a => a.Object.TARGET == Convert.ToInt32( oldValue));

            await firebase
                .Child(ChildProgram)
                .Child(toUpdatePerson.Key)
                .PutAsync(viewProgramModel);
            GetAllData();
        }
        public async Task DeleteViewProgramModel(string mode)
        {
            var toDeletePerson = (await firebase
               .Child(ChildProgram)
               .OnceAsync<ViewProgramModel>()).FirstOrDefault(a => a.Object.MODE == mode);
            await firebase.Child(ChildProgram).Child(toDeletePerson.Key).DeleteAsync();
            GetAllData();

        }

        public async void GetAllData()
        {
            _returnedEvents.Clear();

            var programs = await firebase.Child(ChildProgram).OnceAsync<ViewProgramModel>();
            for (int i = 0; i < programs.Count; i++)
            {
                _returnedEvents.Add(programs.ElementAt(i).Object);
            }
        }
        public async void listenForEvents()
        {
            _returnedEvents.Clear();

            var programs = await firebase.Child(ChildProgram).OnceAsync<ViewProgramModel>();
            for (int i = 0; i < programs.Count; i++)
            {
                _returnedEvents.Add(programs.ElementAt(i).Object);
            }

            //returnedEvents = firebase.Child(ChildProgram).OrderByKey().AsObservable<ViewProgramModel>()
            //    .Subscribe(eventReceived =>
            //    {
            //    if (eventReceived.EventType == Firebase.Database.Streaming.FirebaseEventType.InsertOrUpdate)
            //    {

            //        var found = _returnedEvents.FirstOrDefault(i => i._KEY == eventReceived.Key);

            //        if (found == null)
            //        {
            //            // not in observable collection, add it
            //            _returnedEvents.Add(eventReceived.Object);
            //        }
            //        else
            //        {
            //            // event was updated
            //            int tempIndex = _returnedEvents.IndexOf(found);
            //            _returnedEvents[tempIndex] = eventReceived.Object;
            //        }
            //    }
            //});
        }
    }
}

Вот CookPage.xaml

    <StackLayout>
        <Button Text="add" Clicked="Button_Clicked"></Button>

        <Button Text="delete" Clicked="Button_Clicked_1"></Button>
        <Syncfusion:SfDataGrid x:Name="sfGrid" ItemsSource="{Binding _returnedEvents, Mode=TwoWay} " >
        </Syncfusion:SfDataGrid>

    </StackLayout>

Вот код около CookPage.cs.

  [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class CookPage : ContentPage
    {
        FirebaseHelper firebaseHelper = new FirebaseHelper();
        public CookPage()
        {
            InitializeComponent();

            // for Syncfusion DataGrid 
            firebaseHelper.listenForEvents();
            //sfGrid.ItemsSource = ViewProgramModel._returnedEvents;
             BindingContext= firebaseHelper;

            sfGrid.ColumnSizer = ColumnSizer.Star;
            sfGrid.AllowEditing = true;
            sfGrid.NavigationMode = NavigationMode.Cell;
            sfGrid.AllowLoadMore = true;
            sfGrid.AutoGenerateColumns = true;
            //sfGrid.AutoGenerateColumnsMode= AutoGenerateColumnsMode.
            sfGrid.SelectionMode = Syncfusion.SfDataGrid.XForms.SelectionMode.Single;
            sfGrid.AllowPullToRefresh = true;


            sfGrid.CurrentCellEndEdit += SfGrid_CurrentCellEndEdit; ;
        }

        private async void SfGrid_CurrentCellEndEdit(object sender, GridCurrentCellEndEditEventArgs e)
        {
            //throw new System.NotImplementedException();

            var selectObj = sender as SfDataGrid;

            RowColumnIndex index = e.RowColumnIndex;
            int selectColumnIndex = index.ColumnIndex; //2
            int selectRowIndex = index.RowIndex;       //3
            var ob=firebaseHelper._returnedEvents;
            ViewProgramModel selectObject =ob[selectRowIndex-1];
            var newVale = e.NewValue.ToString();
            var oldeValue = e.OldValue.ToString();

            //Here just judge TARGET Column, you should judge all Columns
            if (selectColumnIndex == 2)
            {
                selectObject.TARGET = Convert.ToInt32(newVale);
            }
            //If you want to achieve the all Grid change function, you should judge the selectRowIndex for every change 
            //if (selectRowIndex==1)
            //{
            //    selectObject.MODE = newVale;
            //}else if (selectRowIndex==2)
            //{
            //    selectObject.TARGET = Convert.ToInt32( newVale);
            //}else if (selectRowIndex == 3)
            //{
            //    selectObject.TRIGGER = newVale;
            //}else if (selectRowIndex == 4)
            //{
            //    selectObject.TRIGGERVALUE = Convert.ToInt32(newVale);
            //}

            await firebaseHelper.UpdateViewProgramModel(selectObject, oldeValue);





        }

        private async void Button_Clicked(object sender, System.EventArgs e)
        {

            await firebaseHelper.AddViewProgramModel();
        }

        private async void Button_Clicked_1(object sender, System.EventArgs e)
        {
            await firebaseHelper.DeleteViewProgramModel("test");
        }


    }
...