简短回答:我认为您的模型中不应该有任何 ObservableCollections。模型都应该是需要最小结构完整性的简单类,例如字符串、整数,并且最多是一个 List 用于书籍集合。仅当您打算使用 3rd 方建模框架时才超出此范围,但我离题了。
长答案: MVVM 模式的关键是知道如何正确创建“关注点分离”。这意味着,了解您的模型、您希望这些模型如何在 UI 上显示/行为(即视图模型),以及您希望这些模型如何在 UI 上显示(即视图)。
你的模型是什么?
根据您最初的问题和描述,我想说您只有两个模型:
- 书籍(有一个名称,可能是一个 ID,一个 BookType 枚举器,如 Fiction/Reality/etc...)
- 书店(有一个名称和一个列表来代表他们的整个图书收藏,无论小说/现实/等等。)
你的 ViewModel 是什么?
- BookView 模型。您想从 Book 模型中公开哪些属性?也许它的所有属性,如 Name、ID 和 BookType。或者您可能只想公开 Name 和 BookType。这就是您使用此 ViewModel 保护模型免受直接访问或操纵的方式。
- 书店视图模型。这个视图模型的模型将是一个书店。但是您向 UI 公开的内容应该是:
- 字符串名称(商店名称)
- ObservableCollection 图书(商店的图书收藏)
你的观点是什么?
- 书店视图。这可能是一个包含商店名称文本框的控件,也可能是他们小说书籍的列表视图和现实书籍的另一个列表视图。
部分代码示例:请考虑这个伪代码,而不是可编译的示例。
型号:
public enum BookType
{
Fiction,
Reality,
Other
}
public class Book
{
public string ID { get; set; }
public string Name { get; set; }
public BookType BookType { get; set; }
}
public class Bookstore
{
public string Name { get; set; }
public List<Book> Books { get; set; }
}
视图模型:
// Note: This view model may seem redundant and unnecessary, and 99% of the time it is.
// But by having this ViewModel, you can protect your Book model from direct manipulation,
// or make some properties read-only, etc. I'm not doing it here, but I'm saying you could.
public class BookViewModel : INotifyPropertyChanged
{
public Book Model { get; private set; }
public BookViewModel(Book model)
{
Model = model;
}
public string Name { get => Model.Name; set { Model.Name = value; OnPropertyChanged(); }
public string BookType { get => Model.BookType; set { Model.BookType = value; OnPropertyChanged(); }
}
public class BookstoreViewModel: INotifyPropertyChanged
{
private ObservableCollection<BookViewModel> books = new ObservableCollection<BookViewModel>();
public BookstoreViewModel(Bookstore model)
{
Model = model;
foreach (var book in Model.Books)
{
books.Add(book);
}
}
public ObservableCollection<BookViewModel> FictionBooks
{
get => books.Where(b => b.BookType == BookType.Fiction);
}
public ObservableCollection<BookViewModel> RealityBooks
{
get => books.Where(b => b.BookType == BookType.Reality);
}
public ObservableCollection<BookViewModel> OtherBooks
{
get => books.Where(b => b.BookType == BookType.Other);
}
}
视图:这是一个 WPF 用户控件示例,用于显示有关书店及其书籍的详细信息。
<StackPanel>
<TextBlock Text="{Binding Name}"/>
<ListBox ItemsSource="{Binding FictionBooks}"/>
<ListBox ItemsSource="{Binding RealityBooks}"/>
</StackPanel>