2

我正在尝试在TwoWay模式下绑定MvxBindableListView ,以便当我在ViewModel中设置它的值(通过按钮的单击命令)时它在视图中更新。目前,它仅在开始/tabchange 完全加载布局时更新...

视图模型是:

public List<MyType> TestList
        {
            get { return _testList; }
            set
            {
                _testList = value;
                FirePropertyChanged("TestList");
            }
        }

视图中的 .axml是:

<Mvx.MvxBindableListView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        local:MvxBind="{'ItemsSource':{'Path':'TestList','Mode':'TwoWay'}}"
        local:MvxItemTemplate="@layout/my_item_layout" />
4

2 回答 2

5

数据绑定的工作方式是通过一个名为INotifyPropertyChanged

在这个接口中发生的事情是,每当属性更改时,ViewModel 都会向 View 发送消息 - 例如

    FirePropertyChanged("TestList");

对于列表,如果列表本身的内容发生变化,这将无济于事——例如,当列表添加或删除了一个项目时。


为了解决这个问题,.Net Mvvm 实现包括另一个接口INotifyCollectionChanged

可以实现一个集合——例如一个列表——INotifyCollectionChanged以便让视图知道集合的内容何时发生变化。

例如,该集合可能会触发包含以下提示的事件:

  • 一切都变了——NotifyCollectionChangedAction.Reset
  • 添加了一个项目 - NotifyCollectionChangedAction.Add
  • 一个项目已被删除 - NotifyCollectionChangedAction.Remove
  • ...

大约 12:30 进入 MvvmCross Xaminar http://www.youtube.com/watch?v=jdiu_dH3z5k

研讨会


要将这个接口用于一个小的内存列表 - 例如少于 1000 个“小”对象 - 你所要做的就是改变你List<T>ObservableCollection<T>- ObservableCollection 是核心 .Net 库中的一个类(来自 Microsoft 或 Mono)当您添加/删除列表项时,它将触发正确的事件。

您可以在以下位置查看 Mono ObservableCollection 实现的源代码:https ://github.com/mosa/Mono-Class-Libraries/blob/master/mcs/class/System/System.Collections.ObjectModel/ObservableCollection.cs - 它是值得花一些时间来看看这个实现,这样你就可以更多地了解 Mvvm 如何与 INotifyCollectionChanged 一起工作。

如果您使用 ObservableCollection 类,那么您的代码将变为:

    private ObservableCollection<MyType> _testList;
    public ObservableCollection<MyType> TestList
    {
        get { return _testList; }
        set
        {
            _testList = value;
            FirePropertyChanged("TestList");
            // in vNext use RaisePropertyChanged(() => TestList);
        }
    }

和:

 <Mvx.MvxBindableListView
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    local:MvxBind="{'ItemsSource':{'Path':'TestList'}}"
    local:MvxItemTemplate="@layout/my_item_layout" />

笔记:

  • 绑定是OneWay- 这意味着绑定仍然只是从 ViewModel 到 View -从 View 到 ViewModel没有更新。
  • ObservableCollection 被设计为单线程的——因此请确保对集合的所有更改都在 UI 线程上完成——而不是在工作线程上。InvokeOnMainThread(() => { /* do work here */ })如果需要,您可以使用ViewModel将工作编组回 UI 线程。
  • 在 Android 中,列表的工作方式(通过基本 AdapterView)意味着每次您调用 ObservableCollection 上的任何更新时,UI 列表都会忽略操作提示(添加、删除等)——它将每次更改都视为重置这将导致整个列表重绘。

对于较大的集合 - 您不希望所有项目同时在内存中 - 您可能需要自己实现一些数据存储支持列表。

在https://github.com/slodge/MvvmCross/blob/vnext/Sample%20-%20SimpleDialogBinding/SimpleDroidSql.Core/DatabaseBackedObservableCollection.cs中有一个简单的 sqlite 数据支持存储的简短示例

这种收集数据的虚拟化在 WP 和 WPF 应用程序中很常见 - 例如,请参阅问题和答案,例如WP7 Mango 中的列表框是否默认虚拟化?

于 2012-12-21T10:16:51.403 回答
0

我们刚刚找到了一个适合我们的解决方法!!

注意:从列表中添加和删除会使用新/删除的项目更新视图。但是,对现有项目状态的任何更改都没有反映出来。

解决方案:我们清除了列表并将项目重新添加到具有更新状态的 ViewModel 属性中。然后调用 raisepropertychanged 模拟双向绑定行为。从本质上讲,它是删除所有值并重新添加所有值。

于 2016-03-11T18:16:19.700 回答