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

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

问题描述

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

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:

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

由于我只是添加到列表中,而未将其设置为新列表,因此该设置器将尽早返回并且不触发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屋!

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