Как привязать ListView к коллекции и обновить ее в режиме реального времени - PullRequest
0 голосов
/ 24 июня 2019

Я привязываю свой ListView к моей базе данных Realm, но он не обновляет его, когда я добавляю в него новый элемент.Я добавляю новые элементы, используя другую страницу.

Я использую здесь в качестве ссылки: https://help.syncfusion.com/xamarin/sflistview/mvvm#binding-itemssource

Моя модель:

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; }
    }

Мой 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>

И мой ViewModel (DBServices.GetCategories - это статический метод, который возвращает коллекцию категорий из базы данных Realm. И 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");
            }
        }
    }

Это метод OnPropertyChanged в классе BaseViewModel

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

Когда я нажимаю кнопку на панели инструментов, она открывает новую страницу формы, чтобы создать новую категорию.Затем он просто добавляет эту категорию в базу данных Realm.После этого он появляется сам.Но я не вижу изменений в моем ListView.

РЕДАКТИРОВАТЬ: я вижу новые элементы в ListView, когда я перезапустил приложение.Но я хочу, чтобы он был в списке при добавлении.

Ответы [ 2 ]

0 голосов
/ 24 июня 2019

Вы можете использовать формы Xamarin MessagingCenter , чтобы сообщить ListView, что ему необходимо обновить.

На странице, где новая категория добавляется в БД Царств, в какой-то момент после добавления категории, но до того, как страница будет открыта, вы отправите сообщение, чтобы сообщить странице ListView об обновлении. Это может выглядеть примерно так:

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

В вашей MainViewModel вам нужно подписаться на сообщение и затем действовать в соответствии с ним. Это может быть что-то вроде:

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

При использовании MessagingCenter обратите внимание на два момента.

  1. Передаваемое сообщение должно быть одинаковым для отправителя и подписчика. В этом случае сообщение «Обновление списка». Поскольку оно должно быть идентичным, вы, вероятно, захотите определить сообщение в отдельном классе, чтобы на него могли ссылаться как отправитель, так и подписчик.
  2. При подписке на сообщение необходимо убедиться, что вы отменили подписку. Популярный шаблон - подписываться, когда страница появляется, и отписываться, когда страница исчезает. Хотя другой шаблон может работать лучше для вас.

На заметку о том, что вам не нужно полное определение свойства для Categories. ObservableCollection будет обрабатывать уведомления при добавлении или удалении элементов. Просто установите Categories = new ObservableCollection<Category>(); один раз, а затем только добавляйте или удаляйте элементы. Вам не нужно обновлять его при каждом вызове БД.

0 голосов
/ 24 июня 2019

Чтобы протестировать только XAML и ViewModel, попробуйте заменить DBServices.GetCategories() на ViewModel следующим:

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() также следует проверить на ожидаемый результат, здесь не показанный.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...