要从存储库中获取图书,需要使用一个服务,并且可以在访问相同数据的多个ViewModel中使用它。因此,服务是在ViewModel之间共享数据的好地方。
图书的示例服务实现了泛型接口。这个接口定义了类型ObservableCollection的Items属性。当集合发生变化时,ObservableCollection实现了用于通知的INotifyCollectionChanged接口。接口IItemsService也定义了SelectedItem属性,并使用事件SelectedItemChanged更改通知。除此之外,RefreshAsync、AddOrUpdateAsync和DeleteAsync都是需要由服务类实现的方法:
public interface IItemsService<T> where T : class
{
Task RefreshAsync();
Task<T> AddOrUpdateAsync(T item);
Task<bool> DeleteAsync(T item);
ObservableCollection<T> Items { get; }
T SelectedItem { get; set; }
event EventHandler<T> SelectedItemChanged;
}
类BooksService派生自基类BindableBase,并实现了泛型接口IItemsService。BooksService使用以前创建的SampleBooksRepository,但只需要IBooksRepository接口提供的这个类的功能。该类通过构造函数注入,用于刷新图书列表、添加和更新图书以及删除图书:
public class BooksService : BindableBase, IItemsService<Book>
{
private ObservableCollection<Book> _books = new ObservableCollection<Book>();
private readonly IBooksRepository _booksRepository;
public BooksService(IBooksRepository booksRepository) => _booksRepository = booksRepository;
public ObservableCollection<Book> Items => _books;
private Book _selectedItem;
public Book SelectedItem
{
get => _selectedItem;
set
{
if (SetProperty(ref _selectedItem, value))
{
SelectedItemChanged?.Invoke(this, _selectedItem);
}
}
}
public event EventHandler<Book> SelectedItemChanged;
public async Task<Book> AddOrUpdateAsync(Book item)
{
Book updated = null;
if (item.BookId == 0)
{
updated = await _booksRepository.AddAsync(item); ;
}
else
{
updated = await _booksRepository.UpdateAsync(item);
}
return updated;
}
public async Task<bool> DeleteAsync(Book item)
{
return await _booksRepository.DeleteAsync(item.BookId);
}
public async Task RefreshAsync()
{
IEnumerable<Book> books = await _booksRepository.GetItemsAsync();
_books.Clear();
foreach (var book in books)
{
_books.Add(book);
}
SelectedItem = _books.FirstOrDefault();
}
}
既然服务功能已经就绪,下面就继续讨论ViewModel。