Как обновить существующий элемент ViewModel в ObservableCollection, который заполняется Observable - PullRequest
0 голосов
/ 25 апреля 2018

Имея ObservableCollection, которая заполняется наблюдаемой, я хотел бы знать, какой самый эффективный и правильный способ обновить элемент ViewModel в коллекции, если он уже существует. Я придумал 2 решения:

Раствор 1

Сделайте MainViewModel ответственным, чтобы определить, существует ли элемент в ObservableCollection, если да, выполните обновление:

MainViewModel.cs

private readonly SortedObservableCollection<IConversationPreviewViewModel> _conversationPreviews = new SortedObservableCollection<IConversationPreviewViewModel>();

public void SubscribeOnConversations()
{
    _observeConversationsUseCase
        .Conversations
        .ObserveOn(_schedulerProvider.Dispatcher)
        .Subscribe(OnNext);
}

private void OnNext(Conversation conversation)
{
    var previewViewModel = _conversationPreviews.FirstOrDefault(it => it.ConversationId == conversation.ConversationId);
    if (previewViewModel == null)
    {
        IConversationPreviewViewModel conversationPreview = _conversationPreviewFactory.Create(conversation);
        _conversationPreviews.Add(conversationPreview);
    }
    else
    {
        previewViewModel.UpdateConversation(conversation);
    }
}

Решение 2

Модель основного вида отвечает только за добавление новых элементов, но за обновление отвечает каждая модель представления самого элемента, подписывая каждую на наблюдаемую:

   public class Conversation
        {
            public int Id { get; set; }

            public string Name { get; set; }
        }

public class ConversationItemViewModel
        {
            private int Id { get; set; }

            public string Text { get; private set; }

            public ConversationItemViewModel(Conversation conversation, ObserveConversations observeConversations)
            {
                Id = conversation.Id;
                Text = conversation.Name;

                PrintStatus("ctor");

                observeConversations.Conversations.Where(it => it.Id == Id).Subscribe(OnNext);
            }

            private void OnNext(Conversation conversation)
            {
                Text = conversation.Name;

                PrintStatus("OnNext");
            }

            private void PrintStatus(string from)
            {
                Console.WriteLine($"Id:{Id} Text:{Text} From: {from}");
            }
        }

   public class ObserveConversations
        {
            public IConnectableObservable<Conversation> Conversations { get; }

            public ObserveConversations()
            {
                Conversations = ConversationsArriving();

                Conversations.Connect();
            }

            public IConnectableObservable<Conversation> ConversationsArriving()
            {
                var list = new List<Conversation>() { new Conversation(){Id = 1, Name = "name1"},
                    new Conversation() {Id = 2, Name = "name2" },
                    new Conversation() {Id = 3, Name = "name3"},
                    new Conversation() {Id = 2, Name = "updatedname2"}, // Update this
                    new Conversation() {Id = 4, Name = "name4"},
                    new Conversation() {Id = 3, Name = "updatedname3"}, // Update this
                };

                return list.ToObservable().Delay(TimeSpan.FromSeconds(1)).Publish();
            }
        }

        public class MainViewModel
        {
            private readonly ObserveConversations _observeConversations;

            public MainViewModel(ObserveConversations observeConversations)
            {
                _observeConversations = observeConversations;
            }

            private ObservableCollection<ConversationItemViewModel> ConversationItemViewModels { get; } = new ObservableCollection<ConversationItemViewModel>();

            public void Start()
            {
                _observeConversations.Conversations
                    .Distinct(it => it.Id)
                    .Subscribe(OnNext);
            }

            private void OnNext(Conversation conversation)
            {
                ConversationItemViewModels.Add(new ConversationItemViewModel(conversation, _observeConversations));
            }
        }

class Program
{
    static void Main(string[] args)
    {
        var observeConversations = new ObserveConversations();
        var mainViewModel = new MainViewModel(observeConversations);
        mainViewModel.Start();

        Console.ReadLine();
    }

Лично я считаю решение 2 лучше, так как оно делегирует ответственность за обновление каждому ViewModel каждому себе.

  1. Есть ли более мелкозернистый раствор, чем те?
  2. Может ли создание нескольких подписок для каждого элемента ViewModel в решении 2 создать проблемы с производительностью?
...