【问题标题】:MvvmCross iOS UITableView doesn't update on Property ChangedMvvmCross iOS UITableView 不会在 Property Changed 上更新
【发布时间】:2014-03-04 01:30:18
【问题描述】:

我的表格视图不会在其源属性更改时更新。代码如下:

视图控制器:

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

【问题讨论】:

    标签: ios uitableview xamarin.ios xamarin mvvmcross


    【解决方案1】:

    这是一个棘手的问题。罪魁祸首是 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。

        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 正确更新。

    如果 CollectionChanged 事件能在 UI 线程上自动处理就好了,类似于 RaisePropertyChanged() 的工作原理。

    【讨论】:

    • 这之前已经出现过 - 例如请参阅stackoverflow.com/questions/18170151/… - == 代码行背后的原因是一种优化(以防止多个列表绘制)。如果有人认为这可以或应该以某种方式做得更好(例如,使其成为可选、添加一些跟踪或其他内容),请记录有关它的问题或发送请求请求。
    • Observable Collection 在带有 RecyclerView 的异常中运行:“在适配器 RealNotifyDataSetChanged ArgumentException 期间屏蔽了异常:'jobject' 不得为 IntPtr.Zero”。简单的解决方案是更改回列表,如果您删除或添加项目,请调用 .ToList()
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-06
    • 2015-11-24
    • 1970-01-01
    • 2013-06-22
    • 1970-01-01
    • 2015-05-04
    • 1970-01-01
    相关资源
    最近更新 更多