我移植了我的应用程序以使用Realm数据库而不是SQLite。但是我遇到了IRealmCollection
与MVVM结合的问题。
让我们假设以下模型:
public class Item : RealmObject
{
public string Id { get; }
}
我MainViewModel
的当前方法就是这样:
public class MainViewModel
{
public IRealmCollection<Item> { get; private set; }
}
我现在面临的问题是Item
具有位于ItemViewModel
的特定命令。我希望在保留IRealmCollection
。
ItemViewModel
:
public class ItemViewModel
{
public Item Model { get; private set; }
public ICommand MyCommand { get; private set; }
}
我一直在考虑几种方法,但我想知道是否有更简单的解决方案:
ObservableCollection
.Select()
扩展名从列表中创建ViewModel ItemViewModel
保存在Realm中,并将[Ignored]
属性添加到每个其他属性或命令ItemViewModel
移出到单独的类(如ItemHelper
)并从MainViewModel
解决此问题的最佳方式和最可能是MVVM方式是什么?
答案 0 :(得分:1)
如果您的命令和其他属性很简单,并且可以嵌入到持久性Item
中,我会使用该解决方案。例如,这可能并不总是有效,因为RealmObjects是在访问集合中的索引时动态创建的。 E.g:
var collection = realm.All<Item>();
var a = collection.ElementAt(0);
var b = collection.ElementAt(0);
会为a
和b
提供不同的实例。这意味着您不能依赖RealmObject继承者中的非持久状态。如果这是一个交易破坏者,那么我会建议一个自定义的ObservableCollection包装IRealmCollection
并处理您的ViewModel的投影,然后可以使用合成来公开RealmObject:
public interface IViewModel<T> where T : RealmObject
{
T Item { get; set; }
}
public class MyObservableCollection<TViewModel, TRealmObject> : IReadOnlyList<TViewModel>, INotifyCollectionChanged
where TRealmObject : RealmObject
where TViewModel : IViewModel<TRealmObject>, new()
{
private readonly IRealmCollection<TRealmObject> _collection;
public TViewModel this[int index] => Project(_collection[index]);
private event PropertyChangedEventHandler _propertyChanged;
public event NotifyCollectionChangedEventHandler CollectionChanged
{
add
{
UpdateCollectionChangedSubscriptionIfNecessary(isSubscribed: true);
_collectionChanged += value;
}
remove
{
_collectionChanged -= value;
UpdateCollectionChangedSubscriptionIfNecessary(isSubscribed: false);
}
}
public MyObservableCollection(IRealmCollection<TRealmObject> collection)
{
_collection = collection;
}
private TViewModel Project(TRealmObject obj)
{
return new TViewModel
{
Item = obj
};
}
private void UpdateCollectionChangedSubscriptionIfNecessary(bool isSubscribed)
{
if (_collectionChanged == null)
{
if (isSubscribed)
{
// Subscribe via _collection
}
else
{
// Unsubscribe via _collection
}
}
}
}