Using CurrentCellEndEdit to update IRealObject or bind DataGrid to ViewModel
Hi,
in my Project (based on https://github.com/mongodb/template-app-maui-todo) I have a page (PartyItemsPage) with a datagrid showing the items in my model Partyitem, which is bound to a online Database via Realm/MongoDB. I would like to use the edit-feature of datagrid, which should then update the model and online databse. When ending the editing by pressing enter the following error message pops up:
Realms.Exceptions.RealmInvalidTransactionException: 'Cannot modify managed objects outside of a write transaction.'
I asked chatGPT for help and it recommended to either insert a new viewmodel in between the datagrid and the model or use a event handler to triggers the Realms write command. I think "CurrentCellEndEdit" would be the one to go for, but I can't get it to run.
Hope you can help me and thanks in advance,
Toby
The Model PartyItems.cs:
public partial class Partyitem : IRealmObject
{
[PrimaryKey]
[MapTo("_id")]
public ObjectId Id { get; set; } = ObjectId.GenerateNewId();
[MapTo("owner_id")]
[Required]
public string OwnerId { get; set; }
public bool IsMine => OwnerId == RealmService.CurrentUser.Id;
[MapTo("partyname")]
[Required]
public string PartyName { get; set; }
The Viewmodel PartyItemsViewModel.cs:
public partial class PartyItemsViewModel : BaseViewModel
{
[ObservableProperty]
private string connectionStatusIcon = "wifi_on.png";
[ObservableProperty]
private bool isShowAllTasks;
[ObservableProperty]
private IQueryable<Partyitem> partyitems;
[ObservableProperty]
public string dataExplorerLink = RealmService.DataExplorerLink;
private Realm realm;
private string currentUserId;
private bool isOnline = true;
[RelayCommand]
public void OnAppearing()
{
realm = RealmService.GetMainThreadRealm();
currentUserId = RealmService.CurrentUser.Id;
Partyitems = realm.All<Partyitem>().OrderBy(i => i.Id).Where(i => i.OwnerId == RealmService.CurrentUser.Id);
}
The Page PartyItemsPage.xaml:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MyApp.Views.PartyItemsPage"
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
xmlns:vm="clr-namespace:MyApp.ViewModels"
xmlns:syncfusion="clr-namespace:Syncfusion.Maui.DataGrid;assembly=Syncfusion.Maui.DataGrid"
xmlns:helpers="clr-namespace:MyApp.Helpers"
x:Name="partyitemsPage">
<ContentPage.Behaviors>
<toolkit:EventToCommandBehavior
EventName="Appearing"
Command="{Binding AppearingCommand}" />
</ContentPage.Behaviors>
<ContentPage.BindingContext>
<vm:PartyItemsViewModel />
</ContentPage.BindingContext>
<syncfusion:SfDataGrid
x:Name="dataGrid"
AutoGenerateColumnsMode="None"
ItemsSource="{Binding Partyitems}"
SortingMode="Single"
AllowEditing="True"
SelectionMode="Single"
NavigationMode="Cell">
<syncfusion:SfDataGrid.Columns>
<syncfusion:DataGridTextColumn HeaderText="Name"
MappingName="PartyName"/>
</syncfusion:SfDataGrid.Columns>
</syncfusion:SfDataGrid>
The Realms Write command used in the example app to edit items:
public partial class EditItemViewModel : BaseViewModel, IQueryAttributable
{
[ObservableProperty]
private Item initialItem;
[ObservableProperty]
private string summary; //summary is in my case the variable Partyname in Partyitems
[ObservableProperty]
private string pageHeader;
public void ApplyQueryAttributes(IDictionary<string, object> query)
{
if (query.Count > 0 && query["item"] != null) // we're editing an Item
{
InitialItem = query["item"] as Item;
Summary = InitialItem.Summary;
PageHeader = $"Modify Item {InitialItem.Id}";
}
else // we're creating a new item
{
Summary = "";
PageHeader = "Create a New Item";
}
}
[RelayCommand]
public async Task SaveItem()
{
var realm = RealmService.GetMainThreadRealm();
await realm.WriteAsync(() =>
{
if (InitialItem != null) // editing an item
{
InitialItem.Summary = Summary;
}
else // creating a new item
{
realm.Add(new Item()
{
OwnerId = RealmService.CurrentUser.Id,
Summary = summary
});
}
});
await Shell.Current.GoToAsync("..");
}
Hi, I created a example app recreating the error. maybe this helps with fxing it.
The dummy Login would be:
Email: [email protected]
Password: testtest
The datagrid shows the item Summary saying "Hello Syncfusion". When you edit the item and press enter to end the editing, the error occurs.
Thanks in advance,
Tobias
Attachment: RealmTodo2master_3bb90f94.zip
Hi Tobias Horn,
Upon reviewing the provided sample on our end, we encountered the same issue
you described. However, our investigation suggests that the problem you're
facing may not be directly related to the DataGrid. Upon further examination,
it appears that the issue may stem from the `realm`.
For more detailed information and assistance regarding this matter, we recommend checking the details provided in the following links and raising any queries in the corresponding pages.
https://www.mongodb.com/community/forums/t/error-cannot-update-obj-outside-of-write-transaction-while-in-a-write-transaction/188438
https://stackoverflow.com/questions/48886931/cannot-modify-managed-objects-outside-of-a-write-transaction-realm-android
Regards,
Tamilarasan
Hi,
thx for your reply. Indeed the issue was with Realm.
The workaround (if anyone faces the same issue) would be to create a dummyitem model. you bind the realm object to the dummy and feed the dummy to the datagrid. then, the endeditcell hook works to trigger the realm write task as the realm object is not changed by edit directly.
Hi Tobias,
Would you be willing to give a little more detail about your solution? A code fragment?
I also can't sorting to work in a datagrid bound to Realm and think your approach may be what I need.
Dave G
- 4 Replies
- 3 Participants
- Marked answer
-
TH Tobias Horn
- Jan 16, 2024 10:57 PM UTC
- May 4, 2024 09:46 PM UTC