Not displaying items from Cosmos db - xamarin.forms

I have issuse with my display method. I have been following tutorial on MSToDo items for xamarin. https://github.com/Azure-Samples/azure-cosmos-db-sql-xamarin-getting-started
I am able to insert in the database so i know it works but cant get anything out of the database. Can you help me please?
this is my get method
static DocumentClient docClient = null;
static readonly string databaseName = "xxxxx";
static readonly string collectionName = "xxxxx";
static bool Initialize() //connection
{
if (docClient != null)
return true;
try
{
docClient = new DocumentClient(new Uri(AppConstants.CosmosEndpointUrl), AppConstants.CosmosAuthKey);
}
catch (Exception ex)
{
Debug.WriteLine(ex);
docClient = null;
return false;
}
return true;
}
public async static Task<List<Post>> GetPosts()
{
var posts = new List<Post>();
if (! Initialize())
return posts;
var postQuery = docClient.CreateDocumentQuery<Post>(
UriFactory.CreateDocumentCollectionUri(databaseName, collectionName),
new FeedOptions { MaxItemCount = 1, EnableCrossPartitionQuery = true })
.OrderBy(i => i.Date)
.AsDocumentQuery();
while (postQuery.HasMoreResults)
{
var queryResults = await postQuery.ExecuteNextAsync<Post>();
posts.AddRange(queryResults);
}
return posts;
}
public class PostViewModel : BaseViewModel
{
List<Post> posts;
public PostViewModel()
{
Posts = new List<Post>();
RefreshCommand = new Command(async () => await ExecuteRefreshCommand());
}
private PostViewModel _selectedAd;
//private ObservableCollection<Post> _posts;
public List<Post> Posts { get => posts; set { posts = value; OnPropertyChanged(); } }
public ICommand RefreshCommand { get; }
async Task ExecuteRefreshCommand()
{
if (IsBusy) return;
IsBusy = true;
try
{
Posts = await AdService.GetPosts();
}
finally
{
IsBusy = false;
}
}
}
HOmePage
PostViewModel postViewModel;
public HomePage()
{
InitializeComponent();
postViewModel = new PostViewModel();
BindingContext = postViewModel;
}
protected override void OnAppearing()
{
base.OnAppearing();
postViewModel.RefreshCommand.Execute(null);
}
And my xaml
<ListView
ItemsSource="{Binding Posts}" x:Name="AdLogListView"
ItemTemplate="{StaticResource HomePageTemplate}"
SelectionMode="Single" Margin="12,0">

The Binding Source Path should be Posts and not Post. Your modified xaml would be:-
<ListView
ItemsSource="{Binding Posts}" x:Name="AdLogListView"
ItemTemplate="{StaticResource HomePageTemplate}"
SelectionMode="Single" Margin="12,0">

Related

How to properly call local storage class?

I've just implemented some localStorage functions in a class to a song lyrics app I'm developing and I think I'm calling it wrong in some way but not sure how. Either that or something is blocking the async function from completing.
Storage Class
public class Sections
{
readonly string searchesFileName = "RecentSearches.txt";
readonly string songsFileName = "RecentSongs.txt";
readonly string playlistFileName = "Playlists.txt";
IFolder localFolder = FileSystem.Current.LocalStorage;
public async void VerifySectionFiles()
{
ExistenceCheckResult searchFileExists = await localFolder.CheckExistsAsync(searchesFileName);
if (searchFileExists != ExistenceCheckResult.FileExists)
{
await localFolder.CreateFileAsync(searchesFileName, CreationCollisionOption.FailIfExists);
}
ExistenceCheckResult songsFileExists = await localFolder.CheckExistsAsync(songsFileName);
if (songsFileExists != ExistenceCheckResult.FileExists)
{
await localFolder.CreateFileAsync(songsFileName, CreationCollisionOption.FailIfExists);
}
ExistenceCheckResult playlistFileExists = await localFolder.CheckExistsAsync(playlistFileName);
if (playlistFileExists != ExistenceCheckResult.FileExists)
{
await localFolder.CreateFileAsync(playlistFileName, CreationCollisionOption.FailIfExists);
}
}
public async void AddRecentSong(string title, int id, string artist)
{
Song[] recentSongs = await ReadRecentSongsFromFile() ?? new Song[10];
recentSongs[9] = null;
for (int i = 9; i > 0; i--)
{
recentSongs[i] = recentSongs[i - 1];
}
recentSongs[0] = new Song(title, artist, id);
IFile songFile = await localFolder.CreateFileAsync(songsFileName, CreationCollisionOption.OpenIfExists);
string songsJsonString = JsonConvert.SerializeObject(recentSongs);
await songFile.WriteAllTextAsync(songsJsonString);
}
public async Task<Song[]> ReadRecentSongsFromFile()
{
IFile recentSongs = await localFolder.CreateFileAsync(songsFileName, CreationCollisionOption.OpenIfExists).ConfigureAwait(false);
string songsJsonString = await recentSongs.ReadAllTextAsync();
Song[] songsArray = JsonConvert.DeserializeObject<Song[]>(songsJsonString);
return songsArray;
}
public async void AddRecentSearch(string searchTerm)
{
string[] recentSearches = await ReadRecentSearchesFromFile() ?? new string[10];
recentSearches[9] = null;
for (int i = 9; i > 0; i--)
{
recentSearches[i] = recentSearches[i - 1];
}
recentSearches[0] = searchTerm;
IFile songFile = await localFolder.CreateFileAsync(songsFileName, CreationCollisionOption.OpenIfExists);
string songsJsonString = JsonConvert.SerializeObject(recentSearches);
await songFile.WriteAllTextAsync(songsJsonString);
}
public async Task<string[]> ReadRecentSearchesFromFile()
{
IFile recentSearches = await localFolder.CreateFileAsync(searchesFileName, CreationCollisionOption.OpenIfExists);
string searchesJsonString = await recentSearches.ReadAllTextAsync();
string[] searchesArray = JsonConvert.DeserializeObject<string[]>(searchesJsonString);
return searchesArray;
}
public async void CreatePlaylist(Playlist playlist)
{
List<Playlist> playlists = await ReadPlaylistsFromFile()?? new List<Playlist>();
playlists.Add(playlist);
IFile playlistsFile = await localFolder.CreateFileAsync(playlistFileName, CreationCollisionOption.OpenIfExists);
string playlistsJsonString = JsonConvert.SerializeObject(playlists);
await playlistsFile.WriteAllTextAsync(playlistsJsonString);
}
public async void RemovePlaylist(Playlist playlist)
{
List<Playlist> playlists = await ReadPlaylistsFromFile() ?? new List<Playlist>();
Playlist playlistToRemove = playlists.Find(x => x == playlist);
playlists.Remove(playlistToRemove);
IFile playlistsFile = await localFolder.CreateFileAsync(playlistFileName, CreationCollisionOption.OpenIfExists);
string playlistsJsonString = JsonConvert.SerializeObject(playlists);
await playlistsFile.WriteAllTextAsync(playlistsJsonString);
}
public async Task<List<Playlist>> ReadPlaylistsFromFile()
{
IFile playlists = await localFolder.CreateFileAsync(playlistFileName, CreationCollisionOption.OpenIfExists);
string playlistsString = await playlists.ReadAllTextAsync();
List<Playlist> playlistList = JsonConvert.DeserializeObject<List<Playlist>>(playlistsString);
return playlistList;
}
}
And when it comes to the implementation, I've used both this by instantiating the class inside the page I'm using it:
public partial class MainPortrait : ContentView
{
Sections sections = new Sections();
public string[] RecentSearches = new string[10];
public string Search { get; set; }
public MainPortrait()
{
InitializeComponent();
BindingContext= this;
sections.VerifySectionFiles();
RecentSearches = sections.ReadRecentSearchesFromFile().Result;
//Do stuff with returned string[]
}
And this, where I added it to the App.xaml.cs
public partial class MainPortrait : ContentView
{
public string[] RecentSearches = new string[10];
public string Search { get; set; }
public MainPortrait()
{
InitializeComponent();
BindingContext= this;
((App)App.Current).sections.VerifySectionFiles();
RecentSearches = ((App)App.Current).sections.ReadRecentSearchesFromFile().Result;
//Do stuff with returned string[]
and it had the same problem both times, so I'm assuming it's a problem with the function itself. And if that's the case, there is probably a similar problem with all the functions in the Section class.
Any ideas?

Xamarin application not navigating back

Problem
This is the process:
Select a category from list.
Load Tasks page.
Tasks are loaded depending on the categoryId selected from the previous page. (Navigate back to Category page is possible ✔️)
Select a Task from from list.
Load Task Page.
Task details are loaded on the page. (Navigate back to Tasks page is not possible ❌)
Video
Question
I do not understand why I cannot navigate back a page. How can I fix this?
Code
CategoriesViewModel
public class CategoriesViewModel : BaseViewModel
{
public ObservableCollection<CategoryModel> Categories { get; } = new ObservableCollection<CategoryModel>();
public Command LoadCategoriesCommand { get; }
public Command<CategoryModel> SelectedCategory { get; }
public CategoriesViewModel()
{
Title = "Categories";
LoadCategoriesCommand = new Command(async () => await LoadCategories());
SelectedCategory = new Command<CategoryModel>(OnSelectedCategory);
}
private async Task LoadCategories()
{
IsBusy = true;
try
{
Categories.Clear();
var categories = await DatabaseService.GetCategoriesAsync();
foreach (var category in categories)
{
this.Categories.Add(category);
}
}
catch (Exception)
{
throw;
}
finally
{
IsBusy = false;
}
}
private async void OnSelectedCategory(CategoryModel category)
{
if (category == null)
return;
await Shell.Current.GoToAsync($"{nameof(TasksPage)}?{nameof(TasksViewModel.CategoryId)}={category.CategoryId}");
}
public void OnAppearing()
{
IsBusy = true;
}
}
TasksViewModel
[QueryProperty(nameof(CategoryId), nameof(CategoryId))]
public class TasksViewModel : BaseViewModel
{
public ObservableCollection<TaskModel> Tasks { get; } = new ObservableCollection<TaskModel>();
private int categoryId;
public int CategoryId
{
get { return categoryId; }
set
{
categoryId = value;
}
}
public Command LoadTasksCommand { get; set; }
public Command<TaskModel> SelectedTask { get; set; }
public TasksViewModel()
{
Title = "Tasks";
LoadTasksCommand = new Command(async () => await LoadTasks());
SelectedTask = new Command<TaskModel>(OnSelectedTask);
}
private async Task LoadTasks()
{
IsBusy = true;
try
{
this.Tasks.Clear();
var tasks = await DatabaseService.GetTasksAsync(CategoryId);
foreach (var task in tasks)
{
this.Tasks.Add(task);
}
}
catch (Exception)
{
throw;
}
finally
{
IsBusy = false;
}
}
private async void OnSelectedTask(TaskModel task)
{
if (task == null)
return;
await Shell.Current.GoToAsync($"{nameof(TaskPage)}?{nameof(TaskViewModel.TaskId)}={task.TaskId}");
}
public void OnAppearing()
{
IsBusy = true;
}
}
TaskViewModel
[QueryProperty(nameof(TaskId), nameof(TaskId))]
public class TaskViewModel : BaseViewModel
{
private int taskId;
public int TaskId
{
get { return taskId; }
set
{
taskId = value;
}
}
private string taskTitle;
public string TaskTitle
{
get { return taskTitle; }
set
{
taskTitle = value;
OnPropertyChanged(nameof(TaskTitle));
}
}
private string description;
public string Description
{
get { return description; }
set
{
description = value;
OnPropertyChanged(nameof(Description));
}
}
public Command LoadTaskCommand { get; }
public TaskViewModel()
{
LoadTaskCommand = new Command(async () => await LoadTask());
}
private async Task LoadTask()
{
IsBusy = true;
try
{
var task = await DatabaseService.GetTaskAsync(TaskId);
this.TaskTitle = task.Title;
this.Description = task.Description;
}
catch (Exception)
{
throw;
}
finally
{
IsBusy = false;
}
}
public void OnAppearing()
{
IsBusy = true;
}
}
Update 1
I tried replacing this line of code in TasksViewModel:
await Shell.Current.GoToAsync($"{nameof(TaskPage)}?{nameof(TaskViewModel.TaskId)}={task.TaskId}");
to this:
await Shell.Current.Navigation.PushAsync(new AboutPage());
Also, the same outcome.
Update 2
As per requested comment, here is the TaskPage.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:vm="clr-namespace:SomeProject.ViewModels"
x:Class="SomeProject.Views.Task.TaskPage"
Title="{Binding TaskTitle}">
<ContentPage.Content>
<RefreshView x:DataType="vm:TaskViewModel"
Command="{Binding LoadTaskCommand}"
IsRefreshing="{Binding IsBusy, Mode=TwoWay}">
<StackLayout>
<Label Text="{Binding Description}" />
</StackLayout>
</RefreshView>
</ContentPage.Content>
</ContentPage>
and TaskPage.xaml.cs:
public partial class TaskPage : ContentPage
{
TaskViewModel _viewModel;
public TaskPage()
{
InitializeComponent();
BindingContext = _viewModel = new TaskViewModel();
}
protected override void OnAppearing()
{
base.OnAppearing();
_viewModel.OnAppearing();
}
}
Update 3
As per requested comment, here is the routes:
public AppShell()
{
InitializeComponent();
Routing.RegisterRoute(nameof(CategoriesView), typeof(CategoriesView));
Routing.RegisterRoute(nameof(TasksPage), typeof(TasksPage));
Routing.RegisterRoute(nameof(TaskPage), typeof(TaskPage));
}
Check your registers route.
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/shell/navigation#register-page-routes
In the Shell subclass constructor, or any other location that runs
before a route is invoked, additional routes can be explicitly
registered for any pages that aren't represented in the Shell visual
hierarchy
I had CategoryPage registered in AppShell.xaml.cs and also AppShell.xaml like so:
<ShellContent Route="CategoryPage" ContentTemplate="{DataTemplate local:CategoryPage}" />
Only can register one route in one or the other.

list view is unable to display data from cloud firestore

Here is my code behind
IIdentifiable is a interface that has Id as property.
I am getting a nullrefrence exceptions while extracting data.
public abstract class SalonService<T> : ISalonService<T> where T : IIdentifiable
{
public Task<T> GetSalonAsync(string id)
{
var tcs = new TaskCompletionSource<T>();
FirebaseFirestore.Instance
.Collection("salons")
.Document(id)
.Get()
.AddOnCompleteListener(new OnDocumentCompleteListener<T>(tcs));
return tcs.Task;
}
public Task<IList<T>> GetSalonsAsync()
{
var tcs = new TaskCompletionSource<IList<T>>();
var list = new List<T>();
FirebaseFirestore.Instance
.Collection("salons")
.Get()
.AddOnCompleteListener(new OnCollectionCompleteListener<T>(tcs));
return tcs.Task;
}
}
And the service listeners for collection of data
public class OnCollectionCompleteListener<T> : Java.Lang.Object, IOnCompleteListener
where T : IIdentifiable
{
private System.Threading.Tasks.TaskCompletionSource<IList<T>> _tcs;
public OnCollectionCompleteListener(System.Threading.Tasks.TaskCompletionSource<IList<T>> tcs)
{
_tcs = tcs;
}
public void OnComplete(Task task)
{
if (task.IsSuccessful)
{
var docsObj = task.Result;
if (docsObj is QuerySnapshot docs)
{
_tcs.TrySetResult(docs.Convert<T>());
}
}
}
}
Service listener to display document
public class OnDocumentCompleteListener<T> : Java.Lang.Object, IOnCompleteListener
where T : IIdentifiable
{
private TaskCompletionSource<T> _tcs;
public OnDocumentCompleteListener(TaskCompletionSource<T> tcs)
{
_tcs = tcs;
}
public void OnComplete(Task task)
{
if (task.IsSuccessful)
{
var docObj = task.Result;
if (docObj is DocumentSnapshot docRef)
{
_tcs.TrySetResult(docRef.Convert<T>());
return;
}
}
// something went wrong
_tcs.TrySetResult(default);
}
}
The Document extension as well
public static class DocumentReferenceExtensions
{
public static T Convert<T>(this DocumentSnapshot doc) where T : IIdentifiable
{
try
{
var jsonStr = Newtonsoft.Json.JsonConvert.SerializeObject(doc.Data.ToDictionary());
var item = Newtonsoft.Json.JsonConvert.DeserializeObject<T>(jsonStr);
item.Id = doc.Id;
return item;
}
catch (Exception)
{
System.Diagnostics.Debug.WriteLine("EXCEPTION THROWN");
}
return default;
}
public static List<T> Convert<T>(this QuerySnapshot docs) where T : IIdentifiable
{
var list = new List<T>();
foreach (var doc in docs.Documents)
{
list.Add(doc.Convert<T>());
}
return list;
}
}
Please let me know what am I missing? I am stuck here

MVVM Media Plugin not displaying picture

i need help with media plugin. I can see that the picture is taken however it doesnt display inthe content page. While debugging the app i can see the path but the picture is not there I have tried to follow this solution, Xamarin Forms MVVM (Prism) with Media.Plugin - How to get a taken picture from device storage
And this solution
Capturing and updating an image source using MVVM in Xamarin
however still nothing. My Binding works fine for everything. Just I dont know how to get the image
<Image
x:Name="Photo"
Grid.Row="2"
HeightRequest="100"
Source="{Binding postViewModel.ImageSource}"
VerticalOptions="Start" />
ViewModel
Ctor
public PostViewModel()
{
TakePictureCommand = new Command(async () => await TakePicture());
}
private async Task TakePicture()
{
await Permission();
var imageSource = await DependencyService.Get<IMessage>().ShowActionSheet(AppResources.AlertPhoto, AppResources.AlertNewPhoto, AppResources.AlertGallery);
if (imageSource == AppResources.AlertNewPhoto)
{
var imageFileName = await CrossMedia.Current.TakePhotoAsync(new StoreCameraMediaOptions()
{
Name = $"{DateTime.UtcNow}.jpg",
DefaultCamera = Plugin.Media.Abstractions.CameraDevice.Rear,
PhotoSize = PhotoSize.Medium,
SaveToAlbum = true
});
if (imageFileName == null)
{
DependencyService.Get<IMessage>().LongAlert(AppResources.AlertNoAcess);
}
else
{
ImageSource = ImageSource.FromStream(() => imageFileName.GetStream());
var test = ImageSource;
}
}
Master VM BInding
protected override void OnAppearing()
{
base.OnAppearing();
BindingContext = MasterPostsView= new MasterPostsViewModel();
}
class MasterPostsViewModel : BaseViewModel
{
public PostViewModel postViewModel { get; set; }
public CategoriesViewModel categoriesViewModel { get; set; }
public MasterPostsViewModel(INavigation navigation)
{
postViewModel = new PostViewModel();
categoriesViewModel = new CategoriesViewModel();
}
}
Have tried also
public string ImageSource { get => _imageSource; set { _imageSource = value; OnPropertyChanged(); } }
ImageSource = imageFileName.AlbumPath;
I have
protected virtual void OnPropertyChanged([CallerMemberName]string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

Xamarin Firebase and Syncfusion DataGrid. How do I listen for Firebase changes?

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:
the 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>();
}
}
I edit your demo, I achieve the update, Add, delete function.
Here is running GIF.
I change your ViewProgramModel like following code. Just move the _returnedEvents to the 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"));
}
}
}
Here is FirebaseHelper.cs, Note: I achieve the update function just for the TARGET Column, I suggest your to add a Primary-key(Auto-increase) for every record in your database to achieve your search function.
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;
// }
// }
//});
}
}
}
Here is 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>
Here is code about 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");
}
}

Resources