这是一种很常见的模式。以下是我在 WPF 中的做法。
在主窗口的视图模型中,应该有一个名为Characters 的属性,即ObservableCollection<CharacterViewModel>。在视图中,这与某种项目控件绑定,例如ListBox。 CharacterViewModel 有一个DataTemplate,或者类实现了ToString(),以便有用地呈现字符。 ListBox 的 SelectedItem 属性绑定到视图模型中的 SelectedCharacter 属性,因此每当用户单击列表框中的项目时,视图模型都知道当前选择的字符是什么。
主窗口视图模型还实现了一个EditingCharacter事件(它只是一个普通的事件处理程序)和一个EditCharacterCommand(使用Josh Smith's RelayCommand pattern),及其附带的属性和方法,例如:
public bool CanEditCharacter { get { return SelectedCharacter != null; } }
public void EditCharacter()
{
EventHandler h = EditingCharacter;
if (EditingCharacter != null)
{
EditingCharacter(this, EventArgs.Empty);
}
}
EditCharacterCommand 绑定到视图中的可点击控件(例如按钮或超链接)。
主窗口view实例化主窗口视图模型并为EditingCharacter事件注册一个处理程序:
private void ViewModel_EditingCharacter(object sender, EventArgs e)
{
CharacterViewModel cvm = ((MainWindowViewModel)sender).SelectedCharacter;
CharacterWindow cw = new CharacterWindow();
cw.ShowDialog(cvm);
}
(为什么使用事件?因为使用事件将创建和显示窗口的实现细节保留在视图模型对象之外。CharacterViewModel 不需要知道有关如何编辑字符的任何细节。它只是引发了一个事件说“嘿,是时候编辑当前选定的角色了。”由主窗口决定在引发事件时它将做什么。)
CharacterWindow 实际上让用户可以编辑一个字符。它的控件绑定到CharacterViewModel 的属性。它实现了ShowDialog的重载:
public bool? ShowDialog(CharacterViewModel cvm)
{
DataContext = cvm;
return ShowDialog();
}
(让读者可以在不保存更改的情况下取消此对话框。)
最后,您还在窗口视图模型中实现AddCharacterCommand - 它创建一个新的CharacterViewModel,将其添加到Characters 集合中,设置SelectedCharacter,并引发@ 987654347@。将此绑定到主窗口中的按钮、超链接或菜单项,就完成了。