So i am new to xamarin forms and i have a problem with my listview. So here is my code.
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>
Here is my contactList page code in 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;
}
}
So the problem is i have this contact listview that is gruoped in alphabetical order. i have this add button that navigates to contact add or edit page and after you add contact it comes back to this page again. So after it comes back to this page it does not update the list. i have been searching for days. I implemented INotifyPropertyChanged in all of my objects. All of my Collections are Observable and as you can see i tried RefreshView too. I checked my whole code with breakpoints and i found out that everything works fine except my list. The thing is the updated data is there, the updated data is bound to MyContactList.ITemSource but my list wont update untill i close the page and open it again. Is it Because of the OnAppearing() event? please help me :(
Sorry my code is a mess right now because i have been trying everything i found on the internet.
EDIT : this is how i add a contact to mylist:
The Button is a ToolbarItem Here is the code:
<ContentPage.ToolbarItems>
<ToolbarItem Text="افزودن مخاطب" IconImageSource="AddIcon.png" Command="{StaticResource NavigateToContactAddOrEditPageCommand}" Order="Primary"/>
</ContentPage.ToolbarItems>
when clicked this command gets executed and then goes to contact add or edit page
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;
}
}
and then it gets added to the database and now i have to call my refresh list method which is this
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);
}
}
and the list is bound to the GroupedData property. and the RefreshList method is on my ContactGroupingViewModel is this
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); }
}
}
INotifyPropertyChanged
? – Jason