public static IListenerRegistration Subscribe <TModel, TViewModel, TKey>(IQuery query,
                                                                          SortedObservableCollection <TViewModel, TModel, TKey> viewModels,
                                                                          Func <TModel, TViewModel> getViewModel,
                                                                          Action?afterSnapshotProcessed = null)
     where TModel : BaseModel
     where TViewModel : IndexedCardViewModel <TModel>
 {
     viewModels.Clear();
     return(query.AddSnapshotListener((snapshot, ex) =>
     {
         if (snapshot is null)
         {
             viewModels.Clear();
         }
         else if (viewModels.Any())
         {
             foreach (var change in snapshot.DocumentChanges)
             {
                 var doc = change.Document;
                 if (change.Type == DocumentChangeType.Added)
                 {
                     viewModels.Add(getViewModel(doc.ToObject <TModel>() !));
                 }
                 else
                 {
                     var vm = viewModels.SingleOrDefault(x => x.UID == doc.Id);
                     if (vm is null)
                     {
                         return;
                     }
                     if (change.Type == DocumentChangeType.Modified)
                     {
                         viewModels.UpdateItem(vm, change.Document.ToObject <TModel>() !);
                     }
                     else
                     {
                         viewModels.Remove(vm);
                     }
                 }
             }
         }
         else if (!snapshot.IsEmpty)
         {
             snapshot.Documents.ForEach(x => viewModels.Add(getViewModel(x.ToObject <TModel>() !)));
         }
         afterSnapshotProcessed?.Invoke();
     }));
 }