This happens on a Xamarin.Forms app. It is a simple app about making lists.
I got two pages: one with the lists and another to show the list's items. The error happens on the latter when I try to add a new item to an ObservableCollection
.
This is a simplified version of the ViewModel:
public ObservableCollection<ListItem> Items { get; }
public Command AddItemCommand { get; }
public ItemsViewModel()
{
Items = new ObservableCollection<ListItem>();
AddItemCommand = new Command(OnAddItem);;
}
private async void OnAddItem()
{
await Device.InvokeOnMainThreadAsync(async () =>
{
if (string.IsNullOrEmpty(NewItemText))
return;
ListItem listITem = new ListItem()
{
ListId = _currentList.ListId,
Id = Guid.NewGuid().ToString(),
Text = NewItemText
};
Items.Add(listITem);
_currentList.ListItems.Add(listITem);
await DataStore.UpdateItemAsync(_currentList);
NewItemText = string.Empty;
});
}
The error happens on the Items.Add(listITem);
call.
Tried wrapping the call on Device.InvokeOnMainThreadAsync
with no luck.
The curious thing is it just happens on the second time I access the page.
The full project can be found on my GitHub: https://github.com/JeffersonAmori/ListApp
CodePudding user response:
It wouldn't surprise me if the error stopped happening if you lessen the chance for XForms to intervene before you've done the Add
. (I'm hypothesizing that the underlying problem is a latent XForms bug.):
private async void OnAddItem()
{
// --- ASSUME we are already on MainThread. ---
// --- Avoid "await" (and any "..Invoke..Async") until after "Items.Add". ---
if (string.IsNullOrEmpty(NewItemText))
return;
ListItem listITem = new ListItem()
{
ListId = _currentList.ListId,
Id = Guid.NewGuid().ToString(),
Text = NewItemText
};
Items.Add(listITem);
_currentList.ListItems.Add(listITem);
NewItemText = string.Empty;
// ----- await Potentially slow operation(s) AFTER all quick UI calls. -----
await DataStore.UpdateItemAsync(_currentList);
}
CAVEAT #1: This doesn't fix any underlying problem, it just might make it happen less often. If its an XF problem, you might have to wrap your code in try..catch
. In catch
, determine if the item got added. If not try adding it again. Messy.
CAVEAT #2: This assumes OnAddItem
is only called from MainThread. That will be true, if you never call it directly yourself - UI code will invoke the command on main thread.
CAVEAT #3: Assumes that all of the types involved (especially ListItem and _currentList.ListItems) are not UI types - they have no dependencies on Xamarin.Forms View classes.