简体   繁体   English

如何将ListView绑定到集合并实时刷新它

[英]How to bind ListView to a collection and refresh it real time

I am binding my ListView to my Realm database, but it doesn't refresh it when I add a new item into it. 我将ListView绑定到我的Realm数据库,但是当我向其中添加新项时它不会刷新它。 I am adding new items using another page. 我正在使用其他页面添加新项目。

I am using here as reference: https://help.syncfusion.com/xamarin/sflistview/mvvm#binding-itemssource 我在这里用作参考: https//help.syncfusion.com/xamarin/sflistview/mvvm#binding-itemssource

My Model: 我的型号:

public class Category : RealmObject
    {
        [PrimaryKey]
        public string CategoryID { get; set; } = Guid.NewGuid().ToString();

        public string CategoryTitle { get; set; }

        public string CategoryDetails { get; set; }

        [Backlink(nameof(Note.CategoryOfNote))]
        public IQueryable<Note> Notes { get; }

        public string CategoryIcon { get; set; }
        public bool IsExpanded { get; set; }
    }

My XAML file containing ListView 我的XAML文件包含ListView

<ContentPage.BindingContext>
        <vm:MainViewModel />
    </ContentPage.BindingContext>
    <ContentPage.ToolbarItems>
        <ToolbarItem Text="NEWCAT" 
                     Clicked="NewCat_Clicked"/>
    </ContentPage.ToolbarItems>

    <ContentPage.Content>

        <ListView x:Name="categoryList"
                  ItemsSource="{Binding Categories}"
                  ItemTapped="ListView_ItemTapped"
                  HasUnevenRows="True">

            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout Orientation="Vertical" 
                                     HorizontalOptions="FillAndExpand"
                                     Padding="10"
                                     Spacing="10">
                            <Label Text="{Binding Path=CategoryTitle}" 
                                   FontSize="Medium"/>
                            <StackLayout IsVisible="{Binding IsExpanded}" 
                                         Orientation="Horizontal"
                                         HorizontalOptions="CenterAndExpand">
                                <Button Text="Notes"
                                        Clicked="NotesButton_Clicked" />
                                <Button Text="Edit" 
                                        Clicked="EditButton_Clicked"/>
                                <Button Text="Delete"
                                        Clicked="DeleteButton_Clicked"/>
                            </StackLayout>
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </ContentPage.Content>

And my ViewModel (DBServices.GetCategories is a static method that returns a collection of categories from Realm DB. And BaseViewModel implements INotifyPropertyChanged) 而我的ViewModel(DBServices.GetCategories是一个静态方法,它返回Realm DB中的类别集合.BaseViewModel实现了INotifyPropertyChanged)

class MainViewModel : BaseViewModel
    {

        private Category _oldCategory;
        public MainViewModel()
        {
            RefreshCategories();
        }

        private void RefreshCategories()
        {
            Categories = new ObservableCollection<Category>(DBServices.GetCategories());
        }


        private ObservableCollection<Category> _Categories;
        public ObservableCollection<Category> Categories
        {
            get
            {
                return _Categories;
            }
            set
            {
                _Categories = value;
                OnPropertyChanged("Categories");
            }
        }
    }

This is OnPropertyChanged method in BaseViewModel class 这是BaseViewModel类中的OnPropertyChanged方法

protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

When I click to the toolbar button, it pushes a new form page to create a new category. 当我单击工具栏按钮时,它会推送一个新的表单页面来创建一个新类别。 Then it just adds that category to the Realm DB. 然后它只是将该类别添加到Realm DB。 Afterwards it pops itself. 然后它弹出自己。 But I see no change in my ListView. 但我看到我的ListView没有变化。

EDIT: I can see new items in ListView when I restarted the app. 编辑:当我重新启动应用程序时,我可以在ListView中看到新项目。 But I want it to be listed as I add them. 但我希望它在我添加它时列出。

To test the XAML and ViewModel only, try replacing DBServices.GetCategories() with the following in the ViewModel: 要仅测试XAML和ViewModel,请尝试使用ViewModel中的以下内容替换DBServices.GetCategories()

public static IEnumerable<Category> TestCategories
{
    get
    {
        yield return new Category { CategoryTitle = "title 1" };
        yield return new Category { CategoryTitle = "title 2" };
    }
}
...
public MainViewModel()
{
    Categories = new ObservableCollection<Category>(TestCategories);
}

DBServices.GetCategories() should also be tested for expected output, not shown here. 还应测试DBServices.GetCategories()的预期输出,此处未显示。

You could use the Xamarin Forms MessagingCenter to tell the ListView it needs to update. 您可以使用Xamarin Forms MessagingCenter告诉它需要更新的ListView。

On the page where the new category is added to the Realm DB, at some point after the category is added but before the page is popped, you would send a message to tell the ListView page to update. 在将新类别添加到Realm DB的页面上,在添加类别之后但在弹出页面之前的某个时刻,您将发送一条消息以告知ListView页面更新。 This may look something like: 这看起来像是这样的:

MessagingCenter.Send(this, "Update listview");

In your MainViewModel you'll need to subscribe to the message and then act upon it. 在您的MainViewModel中,您需要订阅该消息,然后对其进行操作。 This could be something like: 这可能是这样的:

MessagingCenter.Subscribe<AddCategoryPage>(this, "Update listview", (sender) =>
{
    RefreshCategories();
});

Two items to note when using the MessagingCenter. 使用MessagingCenter时需要注意两个事项。

  1. The message passed must be identical between the sender and subscriber. 发送者和订阅者之间传递的消息必须相同。 In this case the message is "Update listview". 在这种情况下,消息是“更新列表视图”。 Because it must be identical, you would probably want to define the message in separate class so it can be referenced by both the sender and subscriber. 因为它必须是相同的,所以您可能希望在单独的类中定义消息,以便发送方和订阅方都可以引用它。
  2. When subscribing to a message you have to make sure that you unsubscribe. 订阅邮件时,您必须确保取消订阅。 A popular pattern is to subscribe when the page appears and unsubscribe when the page disappears. 一种流行的模式是在页面出现时订阅,并在页面消失时取消订阅。 A different pattern may work better for you though. 不过,不同的模式可能对您更有效。

On a side note, you shouldn't need the full property definition for Categories . 另外,您不应该需要Categories的完整属性定义。 The ObservableCollection will handle the notification when items are added or removed. ObservableCollection将在添加或删除项目时处理通知。 Just set Categories = new ObservableCollection<Category>(); 只需设置Categories = new ObservableCollection<Category>(); once and then only add or remove items. 一次然后只添加或删除项目。 You don't need to new it up on every DB call. 您无需在每次数据库调用时重新启动它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM