Search code examples
c#uwprealmtemplate10

passing Realm transaction between ViewModels


Note: this is not the same as Passing Realm objects between ViewControllers

I am trying to find a way to pass a Realm Transaction between two ViewModels. Currently, the Transaction is opened in a detail view, so I can only access it in the detail view. I have a need to Dispose it back in the master view, so I am thinking that I could begin the Transaction before navigating to the detail view, like so:

var trans = realm.BeginWrite();
NavigationService.Navigate(typeof(DetailPage), trans);

However, a Realm Transaction is not serializable, so this method does not work. I am using Template10 in a UWP application. In a Xamarin application (QuickJournal example), this can be accomplished like this:

var transaction = realm.BeginWrite();
...
var page = new JournalEntryDetailsPage(new JournalEntryDetailsViewModel(entry, transaction));
Navigation.PushAsync(page);

As far as I can tell, there isn't a way to pass arguments to a constructor using Template10's NavigationService. I would be happy to be able to either: a) pass the Transaction from the master view to the detail view in the constructor, or b) somehow access the detail view's Transaction from the master view.

My current workaround is to not use a Transaction at all, but to create an unmanaged copy of the RealmObject in the detail view, but this doesn't seem like a great permanent solution.


Solution

  • You could implement a poor man's injection cache to work around the serialization limitation:

    public static class Injector
    {
        private static readonly ConcurrentDictionary<Guid, object> _dict = new ConcurrentDictionary<Guid, object>();
    
        public static Guid Store(object value)
        {
            var key = Guid.NewGuid();
            _dict.TryAdd(key, value);
            return key;
        }
    
        public static object Retrieve(Guid guid)
        {
            if (!_dict.TryRemove(guid, out var result))
            {
                throw new Exception("Key not found");
            }
            return result;
        }
    }
    

    Then in your master ViewModel you could do:

    var key = Injector.Store(realm.BeginWrite());
    NavigationService.Navigate(typeof(DetailPage), key);
    

    And then in your detail ViewModel, you can retrieve the transaction:

    _transaction = Injector.Retrieve(key);