Подтвердить что ты не робот

WPF MVVM Правильный способ запуска события на ViewModel

В моем приложении WPF у меня есть 2 Windows (обе Windows имеют свой собственный ViewModel):

  • Основное окно приложения, отображающее список с кучей слов (привязанных к MainViewModel)

  • Диалоговое окно, которое позволяет пользователям добавлять новые элементы в список (связанный с AddWordViewModel)

В MainViewModel есть свойство Articles List (этот набор заполняется одним из классов сервиса), привязанным к главному окну ListBox

В AddWordViewModel есть SaveWordCommand, который привязан к кнопке Сохранить диалоговое окно добавления Word. Задача состоит в том, чтобы взять текст, введенный пользователем, и передать его в класс обслуживания.

После того, как пользователь нажмет на кнопку "Сохранить", мне нужно уведомить MainViewModel, чтобы перезагрузить статьи из службы.

Моя идея состояла в том, чтобы открыть общедоступную команду в MainViewModel и выполнить ее из AddWordViewModel

Каков правильный способ его реализации?

Спасибо!

4b9b3361

Ответ 1

Агрегаторы событий - неплохой способ решения этой проблемы. В принципе, существует централизованный класс (для упрощения можно сказать, что это Синглтон и встретить возможный гнев антивоенных синглов), который отвечает за передачу событий от одного объекта к другому. С вашими именами классов использование может выглядеть так:

public class MainViewModel
{
    public MainViewModel()
    {
        WordAddedEvent event = EventAggregator.Instance.GetEvent<WordAddedEvent>();
        event.Subscribe(WordAdded);
    }

    protected virtual void WordAdded(object sender WordAddedEventArgs e)
    {
        // handle event
    }
}

public class AddWordViewModel
{    
    //From the command
    public void ExecuteAddWord(string word)
    {
        WordAddedEvent event = EventAggregator.Instance.GetEvent<WordAddedEvent>();
        event.Publish(this, new WordAddedEventArgs(word));
    }
}

Преимущество этого шаблона в том, что вы можете очень легко расширить свое приложение, чтобы иметь несколько способов создания слов и несколько ViewModels, которые заинтересованы в словах, которые были добавлены, и нет связи между ними, чтобы вы могли добавлять и удалять их, как вам нужно.


Если вы хотите избежать синглтона (и для целей тестирования я бы предложил вам это сделать), то, возможно, стоит посмотреть на инъекцию зависимостей, хотя это действительно другая проблема.


Хорошо, последнее соображение. Я вижу, перечитывая ваш вопрос, что у вас уже есть какой-то класс Word Service, который обрабатывает поиск и хранение объектов Word. Нет причин, по которым служба не может нести ответственность за повышение события при добавлении нового слова, поскольку оба ViewModels уже связаны с ним. Хотя я все же предлагаю, что EventAggregator более гибкий и лучшее решение, но YAGNI может применяться здесь

public class WordService
{
    public event EventHandler<WordAddedEventArgs> WordAdded;

    public List<string> GetAllWords()
    {
        //return words
    }

    public void SaveWord(string word)
    {
        //Save word
        if (WordAdded != null) WordAdded(this, new WordAddedEventArgs(word));
        //Note that this way you lose the reference to where the word really came from
        //probably doesn't matter, but might
    }
}

public class MainViewModel
{
    public MainViewModel()
    {
        //Add eventhandler to the services WordAdded event
    }
}

То, что вы хотите избежать, представляет собой соединение между ViewModels, которое вы создадите, вызывая команду на одном ViewModel вместе с другим, это сильно ограничит ваши возможности для расширения приложения (что, если заинтересовать второй ViewModel в новых словах, это теперь ответственность AddWordViewModel, чтобы сказать это тоже?)