MyListView не будет обновлять формы Xamarin

#xamarin #xamarin.forms

#xamarin #xamarin.forms

Вопрос:

Итак, я новичок в xamarin forms, и у меня проблема с моим listview. Итак, вот мой код.

Xaml:

     <RefreshView x:Name="MyContactRefreshView">
    <ListView x:Name="MyContactList"
        Margin="5"   
        ItemsSource="{Binding GroupedData}" 
        IsGroupingEnabled="True"        
        GroupDisplayBinding="{Binding Key}"
        HasUnevenRows="True"
        ItemTapped="GoToContactDetail"
        >
        <ListView.ItemTemplate>
            <DataTemplate>
                <TextCell Text="{Binding Name}" Detail="{Binding Phone1}" x:Name="ContactItem"/>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
    </RefreshView>
 

Вот мой код страницы списка контактов на C#:

     public partial class ContactList : ContentPage
    {
        private readonly ContactListGroupingViewModel _contacts;
        private bool _myContactListItemSourceIsBound;
        public ICommand RefreshCommand { get { return new Command(async() => await RefreshList()); } }

        public ContactList()
        {
            InitializeComponent();
            _contacts = new ContactListGroupingViewModel();
            MyContactRefreshView.Command = RefreshCommand;
            MyContactRefreshView.IsRefreshing = App.ViewModel.isBusy;
            _myContactListItemSourceIsBound = false;
        }
        protected override void OnAppearing()
        {
            MyContactRefreshView.IsRefreshing = true;
            base.OnAppearing();
        }
        private void GoToContactDetail(object sender, ItemTappedEventArgs e)
        {
            new DataLayer.Cummon.Commands.NavigateToContactCommand().Execute(e.Item as ContactObservableModel);
        }
        public async Task RefreshList()
        {
            MyContactRefreshView.IsRefreshing = true;
            MyContactList.SelectedItem = null;
            await _contacts.RefreshList();
            if (_myContactListItemSourceIsBound == false)
            {
                MyContactList.ItemsSource = _contacts.GroupedData;
                _myContactListItemSourceIsBound = true;
            }
            MyContactRefreshView.IsRefreshing = false;
        }
    }
 

Итак, проблема в том, что у меня есть этот список контактов, который группируется в алфавитном порядке. у меня есть эта кнопка добавления, которая переходит на страницу добавления или редактирования контактов, и после добавления контакта она снова возвращается на эту страницу. Поэтому после возврата на эту страницу список не обновляется. я искал несколько дней. Я реализовал INotifyPropertyChanged во всех своих объектах. Все мои коллекции доступны для наблюдения, и, как вы можете видеть, я тоже попробовал RefreshView. Я проверил весь свой код с точками останова и обнаружил, что все работает нормально, кроме моего списка. Дело в том, что обновленные данные есть, обновленные данные привязаны к MyContactList.ItemSource но мой список не будет обновляться, пока я не закрою страницу и не открою ее снова. Это из-за события OnAppearing()? пожалуйста, помогите мне: (

Извините, мой код сейчас в беспорядке, потому что я перепробовал все, что нашел в Интернете.

РЕДАКТИРОВАТЬ: вот как я добавляю контакт в mylist:

Кнопка является элементом панели инструментов, вот код:

     <ContentPage.ToolbarItems>
        <ToolbarItem Text="افزودن مخاطب" IconImageSource="AddIcon.png" Command="{StaticResource NavigateToContactAddOrEditPageCommand}" Order="Primary"/>
    </ContentPage.ToolbarItems>
 

при нажатии эта команда выполняется, а затем переходит на страницу добавления или редактирования контактов

     public class NavigateToContactAddOrEditPageCommand : ICommand
    {
        public event EventHandler CanExecuteChanged;

        public bool CanExecute(object parameter)
        {
            return true;
        }
        public void RaiseCanExecuteChanged()
        {
            var handler = CanExecuteChanged;
            if (handler != null)
            {
                handler(this, EventArgs.Empty);
            }
        }

        public void Execute(object parameter)
        {
            NavigateAsync();
        }
        public async void NavigateAsync()
        {
            await App.MainNavigation.PushAsync(new Pages.ContactAddOrEditPage(), true);
        }
    }
 

in that page i have entries to enter the data then another toolbaritem to add the contact

         <ContentPage.ToolbarItems>
        <ToolbarItem IconImageSource="SubmitIcon.png" Text="ثبت" Order="Primary" Clicked="AddOrEditButton"/>
    </ContentPage.ToolbarItems>
 

when clicked this happen

         private void AddOrEditButton(object sender, EventArgs e)
        {
            ContactObservableModel target = new ContactObservableModel()
            {
                Name = contactName.Text,
                Phone1 = contactPhone1.Text,
                Phone2 = contactPhone2.Text,
                AccountNumber = contactAccountNumber.Text,
                PhoneSocial = contactPhone2.Text
            };
            new DataLayer.Cummon.Commands.AddToContactsCommand().Execute(target);
       }
 

And the command is

  public class AddToContactsCommand : ICommand
    {
        private bool _isBusy = false;
        public event EventHandler CanExecuteChanged;

        public bool CanExecute(object parameter)
        {
            return !_isBusy;
        }
        public void RaiseCanExecuteChanged()
        {
            var handler = CanExecuteChanged;
            if (handler != null)
            {
                handler(this, EventArgs.Empty);
            }
        }

        public void Execute(object parameter)
        {
            AddToContacts(parameter as ContactObservableModel);
            App.MainNavigation.PopAsync();
        }
        public async void AddToContacts(ContactObservableModel contact)
        {
            this._isBusy = true;
            this.RaiseCanExecuteChanged();
            App.ViewModel.isBusy = true;
            await App.ViewModel.ContactListAsync.AddAsync(contact);
            this._isBusy = false;
            this.RaiseCanExecuteChanged();
            App.ViewModel.isBusy = false;
        }
    }
 

а затем он добавляется в базу данных, и теперь я должен вызвать свой метод обновления списка, который заключается в следующем

         public async Task RefreshList()
        {
            this.Items.Clear();
            this.GroupedData.Clear();
            await App.ViewModel.GetContactsItemsAsync();
            var contacts = App.ViewModel.ContactListAsync.OrderBy(n => n.Name).ToList();
            foreach (var contact in contacts)
            {
                this.Items.Add(contact);
            }
            var groupedContacts = Items.OrderBy(p => p.Name)
               .GroupBy(p => p.Name[0].ToString())
               .Select(p => new ObservableGroupCollection<string, ContactObservableModel>(p)).ToList();
            foreach (var contact in groupedContacts)
            {
                this.GroupedData.Add(contact);
            }
        }
 

и список привязан к свойству GroupedData .
и метод RefreshList находится в моей ContactGroupingViewModel, это

     class ContactListGroupingViewModel : ObservableBase
    {
        public ContactListGroupingViewModel()
        {
            Items = new ObservableCollection<ContactObservableModel>();
            GroupedData = new List<ObservableGroupCollection<string, ContactObservableModel>>();
        }
        public async Task RefreshList()
        {
            this.Items.Clear();
            this.GroupedData.Clear();
            await App.ViewModel.GetContactsItemsAsync();
            var contacts = App.ViewModel.ContactListAsync.OrderBy(n => n.Name).ToList();
            foreach (var contact in contacts)
            {
                this.Items.Add(contact);
            }
            var groupedContacts = Items.OrderBy(p => p.Name)
               .GroupBy(p => p.Name[0].ToString())
               .Select(p => new ObservableGroupCollection<string, ContactObservableModel>(p)).ToList();
            foreach (var contact in groupedContacts)
            {
                this.GroupedData.Add(contact);
            }
        }
        private IList<ContactObservableModel> _items;
        public IList<ContactObservableModel> Items
        {
            get { return _items; }
            set { this.SetProperty(ref this._items, value); }
        }
        private List<ObservableGroupCollection<string, ContactObservableModel>> _groupedData;
        public List<ObservableGroupCollection<string, ContactObservableModel>> GroupedData
        {
            get { return _groupedData; }
            set { this.SetProperty(ref this._groupedData, value); }
        }
    }
 

Комментарии:

1. вы конкретно говорите, что проблема возникает при добавлении элемента, но вы не показали никакого кода, который это делает. Кроме того, вы имеете в виду, что нет такой вещи, как INotifyMeProperty INotifyPropertyChanged ?

2. да, я имел в виду, что один извините, я так устал в данный момент, что сейчас совершаю много ошибок. я отредактирую это. я могу показать вам код, но проблема возникает, когда я тоже удаляю контакт, и он не обновит список, пока я не выйду со страницы, но я уверен, что операции добавления и удаления работают нормально, потратив много времени на отладку и установив много точек останова, я увидел, что обновленныйданные привязаны к списку, но список не обновляется. я все еще могу отредактировать сообщение и добавить операции добавления и удаления, если вы хотите.

3. я отредактировал сообщение и добавил операцию добавления.

4. GroupedData должна быть ObservableCollection

5. это ObservableCollection.

Ответ №1:

Вам необходимо использовать ObservableCollection для уведомления ListView о любых изменениях.

Из документа:

Если вы хотите, чтобы ListView автоматически обновлялся по мере добавления, удаления и изменения элементов в базовом списке, вам необходимо использовать ObservableCollection . ObservableCollection определен в System.Collections.ObjectModel и похож на List, за исключением того, что он может уведомлять ListView о любых изменениях:

 ObservableCollection<Employee> employees = new ObservableCollection<Employee>();
listView.ItemsSource = employees;

//Mr. Mono will be added to the ListView because it uses an ObservableCollection
employees.Add(new Employee(){ DisplayName="Mr. Mono"});