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

  • 应用程序的主窗口,显示带有一堆单词的列表(绑定(bind)到MainViewModel)
  • 对话框窗口,允许用户将新项目添加到列表(绑定(bind)到AddWordViewModel)

  • MainViewModel具有绑定(bind)到主窗口的ListBox的List的Articles属性(此集合由服务类之一填充)

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

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

    我的想法是在MainViewModel中公开公共(public)命令,然后从AddWordViewModel执行它

    什么是正确的实现方式?

    谢谢你!

    最佳答案

    Event Aggregators是解决此类问题的一种不错的方法。基本上有一个集中化的类(为了简单起见,我们说它是一个Singleton,面对反单打家伙的可能愤怒),负责将事件从一个对象转移到另一个对象。使用您的类名,用法可能类似于:

    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,并且两者之间没有任何耦合,因此您可以在添加和删除它们时需要。

    如果您想避免单例(出于测试目的,我建议您这样做),那么值得进行依赖注入(inject)研究,尽管那确实是另外一个问题。

    好吧,最后的想法。通过重新阅读您的问题,我发现您已经拥有某种处理Word对象的检索和存储的Word Service类。添加新单词时,由于两个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之间的耦合,这将严重限制您扩展应用程序的选项(如果另一个ViewModel对新单词感兴趣) ,现在也是也要告诉AddWordViewModel的责任吗?)

    10-06 06:45