【问题标题】:Xamarin Forms Listview Not Updating GUIXamarin Forms Listview 不更新 GUI
【发布时间】:2021-06-29 11:00:49
【问题描述】:

我正在尝试创建一个聊天页面。有一个列表视图,其 itemssource 是 ObservableCollection。在将项目添加到 ObservableCollection 之前,一切似乎都很顺利。添加的项目不会立即出现在屏幕上,只有在触摸屏幕后才会显示。

事实上,我也有同样的问题:https://forums.xamarin.com/discussion/18631/listview-binding-to-observablecollection-does-not-update-gui/p2

我相信线程(第 2 页)中所述的解决方案之一与 INotifyPropertyChanged 有关。经过多次尝试应用解决方案以满足我的需求后,我无法这样做。所以请您指导我正确的方向。

我的代码总结如下:

public partial class Chat : ContentPage
{
    private ObservableCollection<MessageObj> Messages = new ObservableCollection<MessageObj>();

    public Chat(string name, string imageURL, int UID)
    {
        msgList.ItemsSource = Messages; //msgList is ListView in XAML
    }

    public class MessageObj
    {
        public string Mess { get; set; }
        public TextAlignment textAlignment { get; set; }

        public MessageObj(string Mess, TextAlignment textAlignment)
        {
            this.Mess = Mess;
            this.textAlignment = textAlignment;
        }
    }
}

我还阅读过:Xamarin Forms ListView ObservableCollection not updating 我想我正在更改收藏,所以我不应该面对这个问题,但我确实是。 任何帮助/见解将不胜感激!

我添加了一个包含我的代码以供参考的要点,其中显示了我现在评论过的不同解决方案的尝试:https://gist.github.com/Dobermensch/49ee9d8adb9a83a38790b691c857691d

编辑:在要点中添加了一些最初省略的代码

Edit2:仅供参考,我没有使用 MVVM 模式。

【问题讨论】:

  • MessageObj 应该继承自 Bindable
  • 在该代码中我没有看到任何将数据添加到 Messages 集合的尝试
  • 我在 OnAppearing() 函数 LoadChat() 的 Messages 集合中添加数据
  • 能否详细说明 1SaeedSalehi?我什至无法从那段简短的声明中想到要在谷歌上搜索什么。
  • @ayudh 将public class MessageObj 更改为public class MessageObj : Bindable,因为需要监控 BindableProperies 的更改或集合更改

标签: listview xamarin xamarin.forms xamarin.android sendbird


【解决方案1】:

我有一个类似的问题,经过大量调试和测试,我发现 GUI 没有更新,因为 ListViewItemsSourcenot 因为 @ 987654323@.

ItemsSource 设置为null,然后使用ObservableCollection 再次设置它会使GUI 更新。
虽然我希望找到更优雅的解决方案,但我找不到。

Device.BeginInvokeOnMainThread(() => {
    Context.WarmupOptions[0].IsChecked = !Context.WarmupOptions[0].IsChecked;
    mylist.ItemsSource = null;
    mylist.ItemsSource = Context.WarmupOptions;
});

【讨论】:

    【解决方案2】:

    正如您在 cmets 中阐明的那样,问题出在 SendBird API 的 OnMessageReceived 回调期间收到的消息。通过阅读他们的文档,他们似乎没有与 UI 线程同步调用回调。

    Xamarin 应用程序可以是多线程的,并且在 UI 的所有更新中必须涉及一个主 UI 线程。在许多应用程序中,您编写的代码都将在 UI 线程上运行,除非您执行 Task.Run()await &lt;some async task&gt;.ConfigureAwait(false) 之类的操作来强制脱离 UI 线程工作。所以通常你不必担心 UI 与非 UI 线程。来自用户与 UI 交互的回调,例如按钮点击,也在 UI 线程上运行。来自非 UI 源的回调可能在也可能不在 UI 线程上(取决于实现和运气),我怀疑这里就是这种情况。

    根据您使用的平台,如果您尝试从不是 UI 线程的代码更改 UI,可能会出现不同的问题。有时您会遇到崩溃(典型的 iOS 响应),或者无法立即更新(常见的 Android 行为)。

    所以我会尝试使用Device.BeginInvokeOnMainThread 强制集合更新发生在 UI 线程上,例如:

            ch.OnMessageReceived = (BaseChannel baseChannel, BaseMessage baseMessage) => {
                Device.BeginInvokeOnMainThread(() =>
                {
                    Messages.Add(new MessageObj(((UserMessage)baseMessage).Message, TextAlignment.Start));
                    msgList.ScrollTo(Messages.Last(), ScrollToPosition.End, false);
                };
            };
    

    这将告诉 UI 线程完成将 MessageObj 添加到 Messages 的工作,因此各种 PropertyChanged 事件也将在 UI 线程上处理,这将知道如何实际更新 UI。

    【讨论】:

    • 我回家后会试一试。手指交叉!
    • @Ayudh 有什么不同吗?
    • 长话短说:您的答案不适用于我现有的代码,但它确实适用于我以前实现相同目标的代码。因此,由于您的建议有助于解决我的问题,我会接受它作为答案。我会尽快更新我的问题,以便您查看。
    猜你喜欢
    • 2019-04-23
    • 2016-10-03
    • 2018-10-16
    • 1970-01-01
    • 2018-10-13
    • 1970-01-01
    • 2019-06-30
    • 2016-09-24
    • 1970-01-01
    相关资源
    最近更新 更多