-
Notifications
You must be signed in to change notification settings - Fork 0
RecyclerView doesn't reflect move operation from an ObservableCollection #310
Comments
Is this with 4.3? Can you please upload a reproduction on github. |
I can make one tonight if needed. But I kinda get the idea how it breaks. The related code is in MvxRecyclerAdapter.cs NotifyDataSetChanged
By moving one entry, both e.NewItems and e.OldItems contains exact same entry. As a result, this.NotifyItemMoved is called with exact same numbers. I think e.NewStartingIndex and e.OldStartingIndex should be utilized instead. |
Hm. |
It should probably be something like |
Maybe our |
BTW I copied code from 4.2. But the main problematic part still keeps. And you get the idea. Another thing to point out, I'm not sure if the Move operation can have multiple items in OldItems & NewItems. The new & old ranges can overlap which would make things more complicated. |
Ugh those indexes can be -1 in the case of single moves/replaces... |
Can you create an adapter inheriting from public override void NotifyDataSetChanged(NotifyCollectionChangedEventArgs e)
{
try
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
if (e.NewStartingIndex == -1)
goto case NotifyCollectionChangedAction.Reset;
NotifyItemRangeInserted(e.NewStartingIndex, e.NewItems.Count);
break;
case NotifyCollectionChangedAction.Move:
if (e.OldStartingIndex == -1 || e.NewStartingIndex == -1)
goto case NotifyCollectionChangedAction.Reset;
for (int i = 0; i < e.NewItems.Count; i++)
{
var oldPosition = e.OldStartingIndex + i;
var newPosition = e.NewStartingIndex + i;
NotifyItemMoved(oldPosition, newPosition);
}
break;
case NotifyCollectionChangedAction.Replace:
if (e.OldStartingIndex == -1)
goto case NotifyCollectionChangedAction.Reset;
NotifyItemRangeChanged(e.OldStartingIndex, e.OldItems.Count);
break;
case NotifyCollectionChangedAction.Remove:
if (e.OldStartingIndex == -1)
goto case NotifyCollectionChangedAction.Reset;
NotifyItemRangeRemoved(e.OldStartingIndex, e.OldItems.Count);
break;
case NotifyCollectionChangedAction.Reset:
NotifyDataSetChanged();
break;
}
}
catch (Exception exception)
{
Mvx.Warning(
"Exception masked during Adapter RealNotifyDataSetChanged {0}. Are you trying to update your collection from a background task? See http://goo.gl/0nW0L6",
exception.ToLongString());
}
} Then test your move and some other operations. |
Yea I did similar workaround for move and it worked. |
According to the MSDN documentation NewStartIndex and OldStartIndex can be -1 for certain operations. This is stupid. When this happens we need to behave as if a Reset occurred. Fixes an issue with Replace where we need to use the old index/items. Fixes an issue with Move where if one item was moved (the default with ObservableCollection) OldItems and NewItems were equal so the new/old positions were equivalent. Fixes #310
Is that the fix though? On Thu, Oct 27, 2016 at 4:52 PM, tttyy [email protected] wrote:
|
Looks good to me. Thanks! |
Steps to reproduce
Declare an ObservableCollection
public ObservableCollection Collection {get;set;} = new ObservableCollection();
// Initialize somewhere
Collection.Add("1");
Collection.Add("2");
Collection.Add("3");
Bind to a RecyclerView using local:MvxBind="ItemsSource Collection"
Call Collection.Move(1, 0);
Expected behavior
Should visually see the second row move up.
Actual behavior
Nothing visually happens
Configuration
Version: 4.x
The text was updated successfully, but these errors were encountered: