【问题标题】:Xamarin.iOS CollectionView - Adding a new element causes the whole list to be refreshedXamarin.iOS CollectionView - 添加新元素会导致整个列表被刷新
【发布时间】:2021-03-29 16:19:13
【问题描述】:

我正在构建一个 xamarin.forms 聊天应用程序,并且只需要添加交付的新元素,在 Android 上我有预期的行为,但 iOS 刷新所有 CollectionView 导致糟糕的用户体验。请查看我的代码(仅相关部分),让我知道我做错了什么,或者我错过了在 iOS 上出现这种行为的原因。

我的 .xaml:

<CollectionView x:Name="ChatCollectionView" 
    SelectionMode="None" HorizontalScrollBarVisibility="Never" 
    VerticalScrollBarVisibility="Always" ItemsUpdatingScrollMode="KeepLastItemInView"
    ItemTemplate="{StaticResource MsgTemplateSelector}" Margin="5,0,5,10">
</CollectionView>

.cs 文件:


public static ReaderWriterLockSlim valuesLock = new ReaderWriterLockSlim();
void ObservableCollectionCallback(IEnumerable collection, object context, Action accessMethod, bool writeAccess)
{
    var collectionLock = (ReaderWriterLockSlim)context;
    Action enterLock = writeAccess ? new Action(collectionLock.EnterWriteLock) : new Action(collectionLock.EnterReadLock);
    Action exitLock = writeAccess ? new Action(collectionLock.ExitWriteLock) : new Action(collectionLock.ExitReadLock);

    enterLock();
    try { accessMethod(); } finally { exitLock(); }
}

ObservableCollection<Msg> ListMsg;

public Page(string userid, string chatkey, string titulo, string foto)
{
    // some code ...
    this.BindingContext = this;
    BindingBase.EnableCollectionSynchronization(ListMsg as IEnumerable, valuesLock,ObservableCollectionCallback);

    List<Msg> recipient = await Task.Run(()=> client.PostData<List<Msg>>("url/msg.php")); 
    //previous line returns a json and deserialize it to a list of "Msg"

    if (recipient != null)
    {
        ListMsg = new ObservableCollection<Msg>(recipient);
        
        ChatCollectionView.ItemsSource = ListMsg;
            
        if (ListMsg.Count > 0)
        {
            if(Device.RuntimePlatform==Device.iOS)
                await Task.Delay(2000);

            ChatCollectionView.ScrollTo(ListMsg.Count - 1, position: ScrollToPosition.End, animate: false);
        }
    }
    else
        ChatCollectionView.ItemsSource = new ObservableCollection<Msg>(); 

    MessagingCenter.Subscribe<MainPage, Msg>("Page", "scroll", async (sender, arg) =>
    {
        Task.WaitAll(tasks.ToArray());

        tasks.Add(Task.Run(async () =>
        {
            arg = await MsgPrepare(arg); //this only changes the element arg not the list
            _ = Device.InvokeOnMainThreadAsync(() =>
            {
                valuesLock.EnterWriteLock();
                try { ListMsg.Add(arg); }
                finally { valuesLock.ExitWriteLock(); }
            });
        }));
    }

}





【问题讨论】:

  • 我不明白ListMsg 和ListaMsg 有什么关系。我也看不到recipient 的来源。 ObservableCollectionCallback 是什么?请更详细地解释代码将如何执行。并且可能需要提供更多代码。
  • 这是一个输入错误,它们是同一个对象,只存在 ListMsg。当然,我会提供更多细节。
  • @ToolmakerSteve 刚刚添加了更多代码以便更好地理解。感谢您的关注。
  • 我在您的代码中看不到任何缺陷。作为测试,如果不使用ObservableCollectionCallback,是否还会出现问题?我想知道支持该功能的 Xamarin 的 iOS 代码是否存在一些限制。 (我意识到代码的存在是有充分理由的;只是想看看 XForms 在内部管理时的行为,没有回调。)

标签: c# xamarin xamarin.forms xamarin.ios nscollectionview


【解决方案1】:

通过“错误”修复它。我添加了涉及整个页面以修复 iOS 软键盘(覆盖了焦点条目元素)和宾果游戏的问题,它已经修复了这两个问题。如果我取下 ScrollView,问题又回来了。我还注意到,如果 ScrollView 仅包含 CollectionView,它就可以工作,它不需要像我的情况那样包含整个页面。另一点是如果您不想要 ScrollView 的滚动功能,您可以设置 Orientation=Neither 来避免它。希望对大家有所帮助。

【讨论】:

    猜你喜欢
    • 2012-04-25
    • 2011-04-20
    • 2017-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-04
    • 2020-09-20
    • 1970-01-01
    相关资源
    最近更新 更多