MvvmCross iOS UITableView不会在“属性更改"上更新 [英] 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:
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:
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); }
}
推荐答案
这是一个棘手的问题.罪魁祸首是MvxTableViewSource中的这一行:
This was a tricky one. The culprit is this line in MvxTableViewSource:
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();
}
}
由于我只是添加到列表中,而未将其设置为新列表,因此该设置器将尽早返回并且不触发ReloadTableData().解决方法是使用ObservableCollection(或其他任何实现INotifyCollectionChanged的东西)代替List.
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(). The fix was to use an ObservableCollection (or anything else that implements INotifyCollectionChanged) instead of a 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); }
}
请注意,由于我的特殊情况,ServerFound事件在单独的线程上被调用.这意味着INotifyCollectionChanged.CollectionChanged事件也将在单独的线程上被调用,因此将服务器添加到列表的操作必须使用InvokeOnMainThread()嫁接到主线程上,以便UI能够正确更新.
Note that because of my particular case, the ServerFound event is being invoked on a separate thread. 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.
最好在UI线程上自动处理CollectionChanged事件,这类似于RaisePropertyChanged()的工作方式.
It would be nice if CollectionChanged events would automatically be handled on the UI thread, similar to how RaisePropertyChanged() works.
这篇关于MvvmCross iOS UITableView不会在“属性更改"上更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!