MvvmCross iOS UITableView 不会更新属性更改 [英] MvvmCross iOS UITableView doesn't update on Property Changed

查看:27
本文介绍了MvvmCross iOS UITableView 不会更新属性更改的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

每当更改其源属性时,我的表视图都不会更新.代码如下:

My table view does not update whenever its source property is changed. The code is as follows:

视图控制器:

    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();
    }

视图模型:

    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:

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();
        }
    }

因为我只是添加到列表中而不是将它设置为新列表,所以 setter 提前返回并且没有触发 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.

如果 CollectionChanged 事件能在 UI 线程上自动处理就好了,类似于 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆