データバインディングが機能する方法は、と呼ばれるインターフェースを介して行われますINotifyPropertyChanged
このインターフェイスで何が起こるかというと、ViewModel はプロパティが変更されるたびに View にメッセージを送信します。
FirePropertyChanged("TestList");
リストの場合、リスト自体の内容が変更された場合 (たとえば、リストに項目が追加または削除された場合)、これは役に立ちません。
これを解決するために、.Net Mvvm の実装には別のインターフェイスが含まれていますINotifyCollectionChanged
。
INotifyCollectionChanged
リストなどのコレクションは、コレクションの内容がいつ変更されたかをビューに知らせるために実装できます。
たとえば、コレクションは、次のようなヒントを含むイベントを発生させる可能性があります。
- すべてが変更されました - NotifyCollectionChangedAction.Reset
- アイテムが追加されました - NotifyCollectionChangedAction.Add
- アイテムが削除されました - NotifyCollectionChangedAction.Remove
- ...
MvvmCross Xaminer http://www.youtube.com/watch?v=jdiu_dH3z5kの 12:30 頃に、このインターフェイスの簡単な紹介があります。
このインターフェイスをメモリ内の小さなリスト (たとえば、1000 未満の「小さな」オブジェクト) に使用するには、次のように変更するだけですList<T>
。ObservableCollectionObservableCollection<T>
はコア .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に、1 つの単純な sqlite データ バックアップ ストアの簡単な例があります。
コレクション データのこの仮想化は、WP および WPF アプリで一般的です。たとえば、WP7 Mango ではリストボックスはデフォルトで仮想化されていますか?