我正在尝试创建一个聊天页面。有一个列表视图,其项目源是一个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;
}
}
}
我也读过:ListView ObservableCollection不更新,我想我正在改变收藏,所以我不应该面对这个问题,但我是任何帮助/洞察力都将不胜感激!
我添加了一个包含我的代码以供参考的要点,它显示了我现在对不同解决方案的评论尝试:https://gist.github.com/Dobermensch/49ee9d8adb9a83a38790b691c857691d
编辑:在gist中添加了一些最初省略的代码
Edit2: FYI,我不使用MVVM模式。
发布于 2019-02-17 18:27:05
正如您在注释中所阐明的,问题在于在OnMessageReceived回调期间从SendBird API接收到的消息。通过阅读他们的文档,他们似乎不会与UI线程同步调用回调。
Xamarin应用程序可以是多线程的,并且有一个主要的UI线程,它必须涉及到UI的所有更新。在许多应用程序中,您编写的代码都将在UI线程上运行,除非您执行Task.Run()
或await <some async task>.ConfigureAwait(false)
之类的操作来强制用户界面线程之外的工作。所以通常您不必担心UI与非UI线程之间的关系。用户与UI交互的回调,就像单击按钮一样,也在UI线程上运行。来自非UI源的回调可能在UI线程上,也可能不在UI线程上(取决于实现和运气),我怀疑情况就是这样。
根据您正在使用的平台的不同,如果尝试从不是UI线程的代码中更改UI,则可能会出现不同的情况。有时您会遇到崩溃(典型的iOS响应),或者只是不会立即更新(常见的安卓行为)。
因此,我要尝试的是使用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添加到消息的工作,因此各种PropertyChanged事件也将在UI线程上处理,后者将知道如何实际更新UI。
发布于 2019-10-08 08:41:32
经过大量的调试和测试,我发现了一个类似的问题: GUI没有更新是因为ListView
的ListView
,而不是因为ObservableCollection
的而不是。
将ItemsSource
设置为null,然后使用ObservableCollection
再次设置它,使GUI更新。
虽然我希望能得到更好的解决办法,但却找不到。
Device.BeginInvokeOnMainThread(() => {
Context.WarmupOptions[0].IsChecked = !Context.WarmupOptions[0].IsChecked;
mylist.ItemsSource = null;
mylist.ItemsSource = Context.WarmupOptions;
});
https://stackoverflow.com/questions/54732669
复制相似问题