.net 将对象添加到ObservableCollection后,UI未更新

k5hmc34c  于 2022-12-14  发布在  .NET
关注(0)|答案(1)|浏览(138)

我正在创建一个带有图书库的应用程序。我可以将图书添加到图书库中,当我重新构建应用程序时,它们会正确显示。但是,我希望图书在添加后立即显示在屏幕上,并考虑使用可观察的集合来实现这一点。
我的收藏集视图:

<CollectionView ItemsSource="{Binding Books}" Margin="36, 20" Grid.Row="1">
    <CollectionView.ItemTemplate>
        <DataTemplate>
             <Border StrokeThickness="3" Margin="0, 0, 0, 4">
                  <Border.Stroke>
                       <LinearGradientBrush EndPoint="0,1">
                                <GradientStop Color="White" Offset="0.1" />
                                <GradientStop Color="{StaticResource Gray950}" Offset="1.0" />
                            </LinearGradientBrush>
                        </Border.Stroke>
                        <Grid HeightRequest="84">
                            <Image Aspect="AspectFill" Source="{Binding ThumbnailSource}"/>
                            <FlexLayout JustifyContent="Center" Direction="Column" HeightRequest="84" Margin="16">
                                <FlexLayout.Background>
                                    <LinearGradientBrush EndPoint="0,1">
                                        <GradientStop Color="#80000000" Offset="0.4"/>
                                        <GradientStop Color="#00000000" Offset="0.9"/>
                                    </LinearGradientBrush>
                                </FlexLayout.Background>
                                <Label FontSize="20" TextColor="White" Text="{Binding Title}" FontAttributes="Bold"/>
                            </FlexLayout>
                        </Grid>
                    </Border>
                </DataTemplate>
    </CollectionView.ItemTemplate>
</CollectionView>

我的视图模型:

namespace eBooks.ViewModel
{
    public partial class LibraryViewModel : ObservableObject
    {
        public LibraryViewModel()
        {
            BookService.OnBooksChanged += RefreshLibrary;
            RefreshLibrary();
        }

        public void RefreshLibrary(List<Book> books = null)
        {
            using var db = new BooksContext();
            _books = new ObservableCollection<Book>(db.Books);
        }

        [ObservableProperty]
        ObservableCollection<Book> _books;
    }
}

我的书模型

namespace eBooks.Models
{
    [Table("Books")]
    public class Book
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }
        public string Title { get; set; }
        public double Progress { get; set; }
        public string ThumbnailData { get; set; }

        public string AudioData { get; set; }
        public string ThumbnailFormat { get; set; }
        public string AudioFormat { get; set; }

        private byte[] _thumbnailData = null;

        public ImageSource ThumbnailSource
        {
            get
            {
                if (_thumbnailData == null || _thumbnailData.Length == 0 && ThumbnailData.Length != 0)
                    _thumbnailData = Convert.FromBase64String(ThumbnailData);

                return ImageSource.FromStream(() => new MemoryStream(_thumbnailData));
            }
        }
    }
}

处理EF Core数据库层操作的服务:

namespace eBooks.Services
{
    public class BookService
    {
        public delegate void BooksChanged(List<Book> books);
        public static event BooksChanged OnBooksChanged;

        public void Add(Book book)
        {
            using var db = new BooksContext();
            db.Books.Add(book);
            db.SaveChanges();
            OnBooksChanged?.Invoke(db.Books.ToList());
        }

        public void Delete(int id)
        {
            using var db = new BooksContext();
            db.Books.Remove(db.Books.Single(book => book.Id == id));
            db.SaveChanges();
            OnBooksChanged?.Invoke(db.Books.ToList());
        }
    }
}

我尝试添加一个'refreshlibrary'方法,当在book服务中调用OnBooksChanged事件时运行,如上面的代码所示。通过向该方法添加断点,我可以看到添加后它包含新添加的图书,但UI仍然不显示该图书。

n6lpvg4x

n6lpvg4x1#

在您的示例中,ObservableCollection与简单的List相比没有任何优势。ObservableCollection的优势在于,如果您操作集合的内容,它将通知对其绑定到的控件的更改。在这里,您不是在操作_books的内容,你每次都给一个新的示例,所以我们假设一开始你有_books中的(Book1, Book2),我们把这个集合命名为A,如果Book3被添加到你的数据库中,你要给_books赋值一个新的集合(Book1, Book2, Book3),我们把这个新的集合命名为B,注意你没有把Book3添加到A,现在你的CollectionView仍然绑定到AA没有改变,因此不会收到更新通知。您需要做的就是确保CollectionView重新评估其绑定并绑定到B。有几种方法可以做到这一点:
1.设置generated属性而不是支持字段,因为它将自动调用OnPropertyChanged

public void RefreshLibrary(List<Book> books = null)
{
    using var db = new BooksContext();
    Books = new ObservableCollection<Book>(db.Books);
}

1.呼叫OnPropertyChanged

public void RefreshLibrary(List<Book> books = null)
{
    using var db = new BooksContext();
    _books = new ObservableCollection<Book>(db.Books);
    OnPropertyChanged("Books");
}

同样,您可以安全地将_books的类型更改为List<Book>,因为在任何地方都不会对它进行操作。

相关问题