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