This is my XAML, just the key part:
<CollectionView ItemsSource="{Binding BookList}"
IsGrouped="False"
ItemsLayout="VerticalGrid, 3"
SelectionChanged="OnTouchBook"
SelectionMode="Single"
x:Name="CV">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="2">
<Grid.RowDefinitions>
<RowDefinition Height="150" />
<RowDefinition Height="15" />
<RowDefinition Height="12" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<Image Grid.Row="0"
Source="{Binding CoverThumb}"
Aspect="AspectFill"
HeightRequest="150"
WidthRequest="100" />
<Label Grid.Row="1"
Text="{Binding Name}"
FontSize="12"
TextColor="Black"
VerticalOptions="Center"/>
<Label Grid.Row="2"
Text="{Binding Author}"
FontAttributes="Italic"
FontSize="10"
TextColor="#8F8F8F"
VerticalOptions="Start"/>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
ViewModel:
public class RemoteViewModel : INotifyPropertyChanged
{
private readonly Dictionary<int, BookModel> DictBooks = new Dictionary<int, BookModel>();
public RemoteViewModel(ICommand _cmd)
{
BookList = new ObservableCollection<BookModel>();
}
private ObservableCollection<BookModel> _BookList;
public ObservableCollection<BookModel> BookList
{
get { return _BookList; }
set
{
if (value != _BookList)
{
_BookList = value;
NotifyPropertyChanged("BookList");
}
}
}
public void SelectedLabel(string label)
{
if (label == "全部")
{
LabelSelected = label;
BookList?.Clear();
BookStore.ForEachLabel((label_name, label_list) =>
{
foreach (ComicBook book in label_list)
{
BookModel model = new BookModel(book) { Store = BookStore, };
BookList?.Add(model);
if (!DictBooks.ContainsKey(model.ID))
DictBooks.Add(model.ID, model);
}
return true;
});
}
else if(BookStore.TryGetBookList(label, out List<ComicBook> comics))
{
LabelSelected = label;
BookList?.Clear();
foreach (ComicBook book in comics)
{
BookModel model = new BookModel(book) { Store = BookStore, };
BookList?.Add(model);
if (!DictBooks.ContainsKey(model.ID))
DictBooks.Add(model.ID, model);
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Model:
public class BookModel : INotifyPropertyChanged
{
public BookStore Store { get; set; }
private string _Name;
public string Name
{
get { return _Name; }
private set
{
if (value != _Name)
{
_Name = value;
NotifyPropertyChanged("Name");
}
}
}
private int _ID;
public int ID
{
get { return _ID; }
private set
{
if (value != _ID)
{
_ID = value;
NotifyPropertyChanged("ID");
}
}
}
private string _Author;
public string Author
{
get
{
if (string.IsNullOrEmpty(_Author)) return "无";
else return _Author;
}
private set
{
if (value != _Author)
{
_Author = value;
NotifyPropertyChanged("Author");
}
}
}
private string _Editor;
public string Editor
{
get
{
if (string.IsNullOrEmpty(_Editor)) return "无";
else return _Editor;
}
private set
{
if (value != _Editor)
{
_Editor = value;
NotifyPropertyChanged("Editor");
}
}
}
private string _EditDate;
public string EditDate
{
get
{
if (string.IsNullOrEmpty(_EditDate)) return "无";
else return _EditDate;
}
private set
{
if (value != _EditDate)
{
_EditDate = value;
NotifyPropertyChanged("EditDate");
}
}
}
public string _Desc;
public string Desc
{
get
{
if (string.IsNullOrEmpty(_Desc)) return "无";
else return _Desc;
}
private set
{
if (value != _Desc)
{
_Desc = value;
NotifyPropertyChanged("Desc");
}
}
}
public ImageSource CoverThumb
{
get
{
if (Comic.NoAbstract)
{
Store.RefreshBookAbstract(Comic.ID);
return null;
}
else if (Comic.Cover != null && Store.TryReadThumbnails(Comic.Cover, out MemoryStream thumb1))
return ImageSource.FromStream(() => { return thumb1; });
else if (Comic.Cover == null && Store.TryReadThumbnails(Comic.GetPage(0), out MemoryStream thumb2))
return ImageSource.FromStream(() => { return thumb2; });
else return null;
}
private set{ NotifyPropertyChanged("CoverThumb"); }
}
public ComicBook Comic { get; private set; }
public BookModel(ComicBook comic) { Refresh(comic); }
public void Refresh(ComicBook comic)
{
Name = comic.BookName;
ID = comic.ID;
Author = comic.BookAuthor;
Comic = comic;
Editor = comic.BookEditor;
EditDate = comic.EditDate.ToString("D");
Desc = comic.Describe;
}
public void RefreshCoverThumb() { CoverThumb = null; }
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}