c# - 在 Realm 中使用特定于项目的 ViewModel 的最佳方式是什么?

标签 c# mvvm uwp realm

我已经将我的应用移植为使用 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; }
}

我一直在考虑几种方法,但我想知道是否有更简单的解决方案:

  • 创建一个订阅 Realm 的自定义 ObservableCollection
  • 使用 LINQ .Select() 扩展从列表中创建一个 ViewModel
  • 在 Realm 中保存 ItemViewModel 并将 [Ignored] 属性添加到每个附加属性或命令
  • 将逻辑从 ItemViewModel 移到一个单独的类(如 ItemHelper)并从 MainViewModel 调用它

解决此问题的最佳且可能最类似于 MVVM 的方法是什么?

最佳答案

如果您的命令和附加属性很简单并且可以嵌入到持久化的 Item 中,我会采用该解决方案。这可能并不总是有效,例如,因为 RealmObjects 是在访问集合中的索引时动态创建的。例如:

var collection = realm.All<Item>();
var a = collection.ElementAt(0);
var b = collection.ElementAt(0);

将为您提供 ab 的不同实例。这意味着您不能依赖 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
            }
        }
    }
}

关于c# - 在 Realm 中使用特定于项目的 ViewModel 的最佳方式是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46267688/

相关文章:

c# - 如何在c#中替换字符串之间的某些字符?

MVVM 模式中的 Silverlight 子窗口

c# - 双败赛数据结构

android - 如何在 2020/21 年获得 Activity 中的 ViewModel 实例?

c# - 如何从 C# 中的字节数组中删除和添加字节

c# - 使用 XML 文件

c# - UWP 闪烁文本

c# - 共享目标 Universal Apps Windows 10 方法

c# - 有没有办法将第三方应用程序的用户作为联系方式添加到人脉应用程序?

c# - For 循环的返回值