给 ObservableCollection 扩展一些列表是好的做法吗?

Is it good practice to give the ObservableCollection extension some Lists?

我正在使用 MVVM 模式在 C# 中编写应用程序。

我的问题是:在我的模型中,我有一些扩展 ObservableCollection 的集合。将三个列表放入模型中的 ObservableCollection 之一是一种好习惯吗?或者应该如何实现?

假设我有一本带有属性的书。这些书都分为两类(现实和虚构)。所以我会创建三个模型:

  1. 图书

  2. BookCollection : ObservableCollection 小说列表 = new Listy(); 列表 reality=new Listy();

  3. BookCollectionCollection : ObservableCollection

简短回答:我认为你的模型中不应该有任何 ObservableCollections。模型都应该是简单的 类,对结构完整性的要求最低,例如字符串、整数,至多是书籍集合的 List。如果您打算使用 3rd 方建模框架,请仅超出此范围,但我离题了。

长答案: MVVM 模式的关键是知道如何正确地创建“关注点分离”。这意味着,了解您的模型,您希望这些模型如何在 UI(即视图模型)上显示为 exposed/behave,以及您希望这些模型如何显示在 UI(即视图).

你的型号是什么?

根据你最初的问题和描述,我会说你只有两个模型:

  1. 图书(有一个名称,可能是一个 ID,一个像 Fiction/Reality/etc 这样的 BookType 枚举器...)
  2. 书店(有一个名称和一个列表来代表他们的整个藏书,不管 fiction/reality/etc。)

你的 ViewModel 是什么?

  1. 图书视图模型。您希望从 Book 模型中公开哪些属性?也许它的所有属性,如 Name、ID 和 BookType。或者您可能只想公开 Name 和 BookType。这就是您通过使用此 ViewModel 来保护模型免受直接访问或操作的方式。
  2. BookstoreViewModel。这个视图模型的模型将是一个书店。但是你暴露给 UI 的应该是:
    • string Name(店铺名称)
    • ObservableCollection Books(商店的藏书)

你有什么看法?

  1. 书店视图。这可能是一个包含商店名称文本框的控件,也可能是他们小说书籍的列表视图和现实书籍的另一个列表视图。

部分代码示例:考虑这个伪代码,而不是一个可编译的示例。

型号:

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>