Xamarin Forms Listview不更新GUI

问题描述 投票:0回答:2

我正在尝试创建一个聊天页面。有一个列表视图,其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模式。

listview xamarin xamarin.forms xamarin.android observablecollection
2个回答
1
投票

正如您在注释中澄清的那样,问题在于从SendBird API在OnMessageReceived回调期间收到的消息。通过阅读他们的文档,他们似乎并没有与UI线程同步调用回调。

Xamarin应用程序可以是多线程的,并且有一个主要的UI线程,必须涉及到UI的所有更新。在许多应用程序中,除非您执行Task.Run()await <some async task>.ConfigureAwait(false)之类的操作来强制从UI线程执行工作,否则您编写的代码都将在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。


0
投票

[经过很多调试和测试后,我发现了类似的问题,因为ItemsSourceListView,GUI没有更新,而由于ObservableCollectionnot,GUI没有更新。] >

ItemsSource设置为null,然后用ObservableCollection再次设置,使GUI得以更新。尽管我希望找到更多的洗脱剂解决方案,但找不到。

Device.BeginInvokeOnMainThread(() => {
    Context.WarmupOptions[0].IsChecked = !Context.WarmupOptions[0].IsChecked;
    mylist.ItemsSource = null;
    mylist.ItemsSource = Context.WarmupOptions;
});
© www.soinside.com 2019 - 2024. All rights reserved.