2

MvxBindableListViewTwoWayモードでバインドしようとしています。これは、 ViewModelで値を設定したときにビューで更新するためです(ボタンのクリック コマンドを使用)。現在、開始/タブ変更時にレイアウトが完全にロードされた場合にのみ更新されます...

ビューモデルは次のとおりです。

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
  • ...

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 ではリストボックスはデフォルトで仮想化されていますか?

于 2012-12-21T10:16:51.403 に答える
0

これについては、私たちにとって有効な回避策が見つかりました!!

注: リストに追加またはリストから削除すると、新しいアイテムまたは削除されたアイテムでビューが更新されます。ただし、既存のアイテムの状態に対する変更は反映されませんでした。

解決策: リストをクリアし、アイテムを更新された状態で ViewModel プロパティに再度追加しました。次に、raisepropertychanged を呼び出すと、双方向のバインド動作が模倣されます。基本的に、すべての値を削除し、すべての値を再度追加していました。

于 2016-03-11T18:16:19.700 に答える