在我的WPF应用程序中,我有2个Windows(两个Windows都有自己的ViewModel):
应用程序的主窗口显示带有一堆单词的列表(绑定到MainViewModel)
允许用户向列表添加新项目的对话框窗口(绑定到AddWordViewModel)
MainViewModel具有List的Articles属性(此集合由其中一个服务类填充)绑定到主窗口的ListBox
AddWordViewModel具有绑定到“添加单词对话框”的“保存”按钮的SaveWordCommand。它的任务是获取用户输入的文本并将其传递给服务类。
用户点击“保存”按钮后,我需要通知MainViewModel从服务中重新加载文章。
我的想法是在MainViewModel中公开public命令并从AddWordViewModel执行它
实施它的正确方法是什么?
谢谢!
答案 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也有责任告诉那个吗?)