[英]MvvmCross iOS UITableView doesn't update on Property Changed
My table view does not update whenever its source property is changed. 每当源属性发生更改时,我的表视图都不会更新。 The code is as follows:
代码如下:
ViewController: 视图控制器:
public override void ViewDidLoad()
{
base.ViewDidLoad();
View.BackgroundColor = UIColor.White;
var table = new UITableView(new RectangleF(0, 80, Device.Width, Device.Height - 80));
Add(table);
var source = new MvxStandardTableViewSource(table, "TitleText SessionInfo");
table.Source = source;
var set = this.CreateBindingSet<JoinSessionViewController, JoinSessionViewModel>();
set.Bind(source).To(vm => vm.AvailableServers);
set.Apply();
table.ReloadData();
}
ViewModel: 视图模型:
private readonly INetworkSessionClient _client;
public JoinSessionViewModel(INetworkSessionClient client)
{
_client = client;
_client.ServerFound += ClientOnServerFound;
_client.BeginSearchingForServers();
}
private void ClientOnServerFound(object sender, ServerFoundEventArgs serverFoundEventArgs)
{
if (AvailableServers.Any(s => s.Identifier == serverFoundEventArgs.ServerInfo.Identifier))
return;
AvailableServers.Add(serverFoundEventArgs.ServerInfo);
RaisePropertyChanged(() => AvailableServers);
}
private List<ServerInfo> _availableServers;
public List<ServerInfo> AvailableServers
{
get { return _availableServers; }
set { _availableServers = value; RaisePropertyChanged(() => AvailableServers); }
}
This was a tricky one. 这是一个棘手的问题。 The culprit is this line in MvxTableViewSource:
罪魁祸首是MvxTableViewSource中的这一行:
https://github.com/MvvmCross/MvvmCross/blob/v3.1/Cirrious/Cirrious.MvvmCross.Binding.Touch/Views/MvxTableViewSource.cs#L56 https://github.com/MvvmCross/MvvmCross/blob/v3.1/Cirrious/Cirrious.MvvmCross.Binding.Touch/Views/MvxTableViewSource.cs#L56
public virtual IEnumerable ItemsSource
{
get { return _itemsSource; }
set
{
if (_itemsSource == value) // **** This one ****
return;
if (_subscription != null)
{
_subscription.Dispose();
_subscription = null;
}
_itemsSource = value;
var collectionChanged = _itemsSource as INotifyCollectionChanged;
if (collectionChanged != null)
{
_subscription = collectionChanged.WeakSubscribe(CollectionChangedOnCollectionChanged);
}
ReloadTableData();
}
}
Since I was only adding to the list and not setting it to a new list, the setter was early returning and not firing ReloadTableData(). 由于我只是添加到列表而没有将其设置为新列表,因此setter提前返回并且未触发ReloadTableData()。 The fix was to use an ObservableCollection (or anything else that implements INotifyCollectionChanged) instead of a List.
解决方法是使用ObservableCollection(或其他任何实现INotifyCollectionChanged的方法)而不是List。
private void ClientOnServerFound(object sender, ServerFoundEventArgs serverFoundEventArgs)
{
if (AvailableServers.Any(s => s.Identifier == serverFoundEventArgs.ServerInfo.Identifier))
return;
// CollectionChanged event is not automatically martialed to UI thread
InvokeOnMainThread(() => AvailableServers.Add(serverFoundEventArgs.ServerInfo));
}
private ObservableCollection<ServerInfo> _availableServers;
public ObservableCollection<ServerInfo> AvailableServers
{
get { return _availableServers; }
set { _availableServers = value; RaisePropertyChanged(() => AvailableServers); }
}
Note that because of my particular case, the ServerFound event is being invoked on a separate thread. 请注意,由于我的特殊情况,ServerFound事件正在一个单独的线程上调用。 That means the INotifyCollectionChanged.CollectionChanged event will also be invoked on a separate thread, so the action of adding the server to the list has to be martialed onto the main thread with InvokeOnMainThread() so that the UI will properly update.
这意味着也将在一个单独的线程上调用INotifyCollectionChanged.CollectionChanged事件,因此必须使用InvokeOnMainThread()将服务器添加到列表中的操作进行策略,以便UI正确更新。
It would be nice if CollectionChanged events would automatically be handled on the UI thread, similar to how RaisePropertyChanged() works. 如果在UI线程上自动处理CollectionChanged事件会很好,类似于RaisePropertyChanged()的工作方式。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.