WPF MVVM从ViewModel在视图上触发事件的正确方法

时间:2009-04-28 17:10:37

标签: .net wpf mvvm binding command

在我的WPF应用程序中,我有2个Windows(两个Windows都有自己的ViewModel):

  1. 应用程序的主窗口显示带有一堆单词的列表(绑定到MainViewModel)

  2. 允许用户向列表添加新项目的对话框窗口(绑定到AddWordViewModel)

  3. MainViewModel具有List的Articles属性(此集合由其中一个服务类填充)绑定到主窗口的ListBox

    AddWordViewModel具有绑定到“添加单词对话框”的“保存”按钮的SaveWordCommand。它的任务是获取用户输入的文本并将其传递给服务类。

    用户点击“保存”按钮后,我需要通知MainViewModel从服务中重新加载文章。

    我的想法是在MainViewModel中公开public命令并从AddWordViewModel执行它

    实施它的正确方法是什么?

    谢谢!

1 个答案:

答案 0 :(得分:18)

Event Aggregators是解决此类问题的一种很好的方法。基本上有一个集中的类(为了简单起见,让我们说它是一个单身人士,并面对反单身人士可能的愤怒),负责将事件从一个对象转移到另一个对象。使用您的类名,用法可能如下所示:

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));
    }
}

这种模式的优点是,您可以非常轻松地扩展您的应用程序,以便有多种创建单词的方法和多个ViewModel,这些ViewModel对已添加的单词感兴趣,并且两者之间没有耦合,因此您可以添加和删除他们你需要的。


如果你想避免使用单例(并且出于测试目的,我建议你这样做)那么可能值得研究依赖注入,尽管这确实是另一个问题。


好的,最后的想法。我从重新阅读你的问题看到你已经有了某种Word Service类来处理Word对象的检索和存储。由于两个ViewModel已经连接到新单词,因此没有理由在添加新单词时服务不负责引发事件。虽然我仍然建议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
    }
}

你想要避免做的是引入你将通过在一个ViewModel上调用命令创建的ViewModel与另一个之间的耦合,这将严重限制你扩展应用程序的选项(如果第二个ViewModel变得有兴趣会怎样)用新的话来说,现在AddWordViewModel也有责任告诉那个吗?)