firebasexamarin.formscrud

My app does not show the updated information in view when I update data Xamarin Forms and FireBase


I am new to Xamarin Forms and I am making an application on a system to manage automotive vehicle maintenance services. So far I can save, modify and show data, when I save new vehicles my view shows them to me and updates to show the vehicle, but when I want to edit the vehicles, I can edit them and the changes are shown in Firebase, but my view is still the same same until I close and open the application again, how can I make these changes visible? Any help will be heartily appreciated

My view

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="CMP.Vistas.Vehiculos"
             NavigationPage.HasNavigationBar="False"
             BackgroundColor="White"
             Visual="Material">
    <StackLayout>
        <Frame BackgroundColor="#D48593"
               HorizontalOptions="FillAndExpand"
               HeightRequest="64"
               Margin="0"
               Padding="0"
               HasShadow="False"
               CornerRadius="0">
            <Label Text="CalMaP"
                   HorizontalOptions="End"
                   VerticalOptions="Center"
                   FontSize="23"
                   FontAttributes="Bold"
                   Margin="0,0,40,0"
                   TextColor="White" />
        </Frame>

        

        <Grid RowDefinitions="*">
            <RefreshView RefreshColor="#D48593"
                         Refreshing="RefreshView_Refreshing"
                         x:Name="RefreshCar">
                <ScrollView>
                    <StackLayout x:Name="ContainerVehiculos"
                                 VerticalOptions="Start"
                                 Margin="10,12,10,0"
                                 Orientation="Vertical"
                                 Spacing="20">

                    </StackLayout>
                </ScrollView>
            </RefreshView>
           
            <ImageButton Source="Iconpause.png"
                         VerticalOptions="EndAndExpand"
                         HorizontalOptions="EndAndExpand"
                         HeightRequest="60"
                         WidthRequest="60"
                         Margin="0,0,30,30"
                         CornerRadius="100"
                         BackgroundColor="White"
                         Command="{Binding NavAddVehiculoCommand}" />
        </Grid>
        

    </StackLayout>
</ContentPage>

my View C#

using CMP.VistaModelo;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace CMP.Vistas
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class Vehiculos : ContentPage
    {
        VMVehiculos vm;
        public Vehiculos()
        {
            InitializeComponent();
            vm = new VMVehiculos(Navigation, ContainerVehiculos);
            BindingContext = vm;
            Appearing += Vehiculos_Appearing;
        }

        private async void Vehiculos_Appearing(object sender, EventArgs e)
        {
            await vm.Mostrarvehiculos(ContainerVehiculos);
        }

       
    }
}

my viewModel:

using CMP.Datos;
using CMP.Modelo;
using CMP.Servicios;
using CMP.VistaModelo.Formularios;
using CMP.Vistas;
using CMP.Vistas.Formularios;
using Firebase.Database.Query;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using Xamarin.Forms;

namespace CMP.VistaModelo
{
    public class VMVehiculos : BaseViewModel
    {
        #region VARIABLES
        Dvehiculos funcion = new Dvehiculos();
        List<MVehiculos> _ListaVehiculos;

        private ObservableCollection<MVehiculos> _MVehiculos;
        #endregion

        #region CONSTRUCTOR
        public VMVehiculos(INavigation navigation, StackLayout Contenedor)
        {
            Navigation = navigation;
            Mostrarvehiculos(Contenedor);

        }

        public VMVehiculos()
        {
        }
        #endregion

        #region OBJETOS

        public List<MVehiculos> ListaVehiculos
        {
            get { return _ListaVehiculos; }
            set { SetValue(ref _ListaVehiculos, value); }
        }
        #endregion

        #region PROCESOS
        public void DibujarVehiculos(MVehiculos Item, StackLayout Contenedor)
        {
            var carril = Contenedor;
            var frame = new Frame
            {
                CornerRadius = 15,
                BackgroundColor = Color.FromRgb(240, 220, 230),
                BorderColor = Color.FromHex("#EEEDED"),
                HasShadow = false,
            };
            var grid = new Grid
            {
                ColumnDefinitions = new ColumnDefinitionCollection
                {
                    new ColumnDefinition{ Width = new GridLength(50) },
                    new ColumnDefinition{ Width = new GridLength(150) },
                    new ColumnDefinition{ Width = new GridLength(83) },
                },
                HorizontalOptions = LayoutOptions.FillAndExpand,
            };
            var image = new Image
            {
                Source = Item.Icono,
                HeightRequest = 50,
                WidthRequest = 50,
                Margin = new Thickness(0, 0, 6, 0),
                HorizontalOptions = LayoutOptions.Start,
            };
            Grid.SetRowSpan(image, 2);
            Grid.SetColumn(image, 0);
            var labelNombre = new Label
            {
                Text = Item.Nombre,
                HorizontalOptions = LayoutOptions.StartAndExpand,
                VerticalOptions = LayoutOptions.Center,
                FontAttributes = FontAttributes.Bold,
            };
            Grid.SetRowSpan(labelNombre, 2);
            Grid.SetColumn(labelNombre, 1);
            var labelKilometraje = new Label
            {
                Text = Item.Kilomtraje.ToString(),
                HorizontalOptions = LayoutOptions.End,
                VerticalOptions = LayoutOptions.Center,
                FontSize = 15,
            };
            Grid.SetRow(labelKilometraje, 0);
            Grid.SetColumn(labelKilometraje, 2);

            var labelEstado = new Label
            {
                Text = Item.Estado,
                HorizontalOptions = LayoutOptions.End,
                VerticalOptions = LayoutOptions.Center,
                FontSize = 15,
                TextColor = Color.FromHex(_Color(Item.Estado))
            };
            Grid.SetRow(labelEstado, 1);
            Grid.SetColumn(labelEstado, 2);

            grid.Children.Add(image);
            grid.Children.Add(labelNombre);
            grid.Children.Add(labelKilometraje);
            grid.Children.Add(labelEstado);
            frame.Content = grid;
            var tap = new TapGestureRecognizer();
            tap.Tapped += async (Object sender, EventArgs e) =>
            {
                await Navigation.PushAsync(new DataVehiculo(Item));
            };
            grid.GestureRecognizers.Add(tap);
            carril.Children.Add(frame);
        }
        public string _Color(string parametro)
        {
            string color = "";
            if (parametro.Equals("En uso"))
            {
                color = "#9A8200";
            }
            else if (parametro.Equals("Disponible"))
            {
                color = "#35B121";
            }
            else if (parametro.Equals("En servicio"))
            {
                color = "#CA1D27";
            }
            return color;
        } 

        public async Task Mostrarvehiculos(StackLayout Contenedor)
        {
            funcion = new Dvehiculos();
            ListaVehiculos = await  funcion.ObtenerVehiculos();
            foreach (var item in ListaVehiculos)
            {
                DibujarVehiculos(item, Contenedor);
            }
        }

        public async Task IraAddVehiculo()
        {
            await Navigation.PushAsync(new AddVehiculo());
        }
        #endregion

        #region COMANDOS
        public ICommand NavAddVehiculoCommand => new Command(async () => await IraAddVehiculo());
        #endregion
    }
}

My Firebase data:

using CMP.Modelo;
using CMP.Servicios;
using Firebase.Database;
using Firebase.Database.Query;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Essentials;


namespace CMP.Datos
{
    public class ConexionFirebase
    {
        public static FirebaseClient FBCliente = new FirebaseClient("https://cmpsoft-260301-default-rtdb.firebaseio.com/");

    }
    internal class Dvehiculos
    {
        public async Task<List<MVehiculos>> ObtenerVehiculos()
        {
            return (await ConexionFirebase.FBCliente
                .Child("Servicios")
                .Child("Vehiculos")
                .OnceAsync<MVehiculos>()).Select(Item => new MVehiculos
                {
                    IdVehiculo = Item.Key,
                    NumeroEconomico = Item.Object.NumeroEconomico,
                    Modelo = Item.Object.Modelo,
                    Nombre = Item.Object.Nombre,
                    Tipo = Item.Object.Tipo,
                    NumeroDeSerie = Item.Object.NumeroDeSerie,
                    Icono = Item.Object.Tipo == "pesado" ? "BttnTruck.png" : "BttnCar.png",
                    Kilomtraje = Item.Object.Kilomtraje,
                    HoraDeUso = Item.Object.HoraDeUso,
                    CantLlantas = Item.Object.CantLlantas,
                    TiempoVidaLlantas = Item.Object.TiempoVidaLlantas,
                    DatosExtras = Item.Object.DatosExtras,
                    Observaciones = Item.Object.Observaciones,
                    Estado = Item.Object.Estado,
                }).ToList();
        }



        public async Task InsertarVehiculo(MVehiculos parametro)
        {
            await ConexionFirebase.FBCliente
                .Child("Servicios")
                .Child("Vehiculos")
                .PostAsync(new MVehiculos()
                {
                    IdVehiculo = parametro.IdVehiculo,
                    NumeroEconomico = parametro.NumeroEconomico,
                    Modelo = parametro.Modelo,
                    Nombre = parametro.Nombre,
                    Tipo = parametro.Tipo,
                    NumeroDeSerie = parametro.NumeroDeSerie,
                    Kilomtraje = parametro.Kilomtraje,
                    HoraDeUso = parametro.HoraDeUso,
                    CantLlantas = parametro.CantLlantas,
                    TiempoVidaLlantas = parametro.TiempoVidaLlantas,
                    DatosExtras = parametro.DatosExtras,
                    Observaciones = parametro.Observaciones,
                    Estado = parametro.Estado
                });
        }
        public async Task<List<MVehiculos>> MostrarVehiculosxIdVehiculo(string IdVehiculo)
        {
            return (await ConexionFirebase.FBCliente
                .Child("Servicios")
                .Child("Vehiculos")
                .OnceAsync<MVehiculos>())
                .Where(a => a.Object.IdVehiculo == IdVehiculo).Select(Item => new MVehiculos 
                {
                    NumeroEconomico = Item.Object.NumeroEconomico
                }).ToList();
        }

        public async Task<List<MVehiculos>> ObtenerVehiculoxId(string IdVehiculo)
        {
            return (await ConexionFirebase.FBCliente
                .Child("Servicios")
                .Child("Vehiculos")
                .OnceAsync<MVehiculos>())
                .Where(a => a.Object.IdVehiculo == IdVehiculo).Select(Item => new MVehiculos
                {
                    IdVehiculo = Item.Key,
                    NumeroEconomico = Item.Object.NumeroEconomico,
                    Modelo = Item.Object.Modelo,
                    Nombre = Item.Object.Nombre,
                    Tipo = Item.Object.Tipo,
                    NumeroDeSerie = Item.Object.NumeroDeSerie,
                    Icono = Item.Object.Tipo == "pesado" ? "BttnTruck.png" : "BttnCar.png",
                    Kilomtraje = Item.Object.Kilomtraje,
                    HoraDeUso = Item.Object.HoraDeUso,
                    CantLlantas = Item.Object.CantLlantas,
                    TiempoVidaLlantas = Item.Object.TiempoVidaLlantas,
                    DatosExtras = Item.Object.DatosExtras,
                    Observaciones = Item.Object.Observaciones,
                    Estado = Item.Object.Estado,
                }).ToList();
        }
        public async Task EditarVehiculo(MVehiculos parametro)
        {
            var data = (await ConexionFirebase.FBCliente
                .Child("Servicios")
                .Child("Vehiculos")
                .OnceAsync<MVehiculos>())
                .Where(a => a.Object.IdVehiculo == parametro.IdVehiculo)
                .FirstOrDefault();
            await ConexionFirebase.FBCliente
                .Child("Servicios")
                .Child("Vehiculos")
                .Child(data.Key)
                .PutAsync(new MVehiculos()
                {
                    IdVehiculo = parametro.IdVehiculo,
                    NumeroEconomico = parametro.NumeroEconomico,
                    Modelo = parametro.Modelo,
                    Nombre = parametro.Nombre,
                    Tipo = parametro.Tipo,
                    NumeroDeSerie = parametro.NumeroDeSerie,
                    Kilomtraje = parametro.Kilomtraje,
                    HoraDeUso = parametro.HoraDeUso,
                    CantLlantas = parametro.CantLlantas,
                    TiempoVidaLlantas = parametro.TiempoVidaLlantas,
                    DatosExtras = parametro.DatosExtras,
                    Observaciones = parametro.Observaciones,
                    Estado = parametro.Estado
                });
        }
    }
}

My Model:

using System;
using System.Collections.Generic;
using System.Text;

namespace CMP.Modelo
{
    public class MVehiculos
    {
        public string IdVehiculo { get; set; }
        public string NumeroEconomico { get; set; }
        public string Modelo { get; set; }
        public string Nombre { get; set; }
        public string Tipo { get; set; }
        public string NumeroDeSerie { get; set; }
        public string Icono { get; set; }
        public int Kilomtraje { get; set; }
        public int HoraDeUso { get; set; }
        public int CantLlantas { get; set; }
        public int TiempoVidaLlantas { get; set; }
        public string DatosExtras { get; set; }
        public string Observaciones {  get; set; }
        public string Estado { get; set; }

    }
}


So far I have tried changing the Firebase code, also the views and changing the code of my viewmodel, but I can't think of what else to do.


Solution

  • As Jason said that MVehiculos needs to implement INotifyPropertyChanged or otherwise be made Observable:

    1. Add the CommunityToolkit.Mvvm nuget package in your project with the Nuget package manager.
    2. Change your MVehiculos class to:
    public partial class MVehiculos : ObservableObject
        {
            [ObservableProperty]
            public string idVehiculo;
            [ObservableProperty]
            public string numeroEconomico;
            [ObservableProperty]
            public string modelo;
            [ObservableProperty]
            public string nombre;
            [ObservableProperty]
            public string tipo;
            [ObservableProperty]
            public string numeroDeSerie;
            [ObservableProperty]
            public string icono;
            [ObservableProperty]
            public int kilomtraje;
            [ObservableProperty]
            public int horaDeUso;
            [ObservableProperty]
            public int cantLlantas;
            [ObservableProperty]
            public int tiempoVidaLlantas;
            [ObservableProperty]
            public string datosExtras;
            [ObservableProperty]
            public string observaciones;
            [ObservableProperty]
            public string estado;
        }
    

    And BaseViewModel class also needs to inherit ObservableObject.

    For more info you can refer to the doc: ObservableProperty attribute.