4

ClearBindings()MvvmCross で の作業はどのように行われますか?

テスト目的で、WeekSelectorView の TableView の itemsSource をクリアしようとしているだけですViewDidLoad()。これが私が試したことですが、何もうまくいかないようです。

(「これ」は、WeekSelectorView の現在のインスタンスを指します)

var source = new WeekSelectorTableSource(TableView, this);
TableView.Source = source;

var set = this.CreateBindingSet<WeekSelectorView, WeekSelectorViewModel>();
set.Bind(source).To(vm => vm.Options);
set.Apply();

//None of these work
this.ClearBindings (this);
this.ClearBindings (source);
this.ClearBindings (TableView.Source);
this.ClearBindings (source.ItemsSource);
this.ClearBindings ("ItemsSource");
this.ClearBindings ("source.ItemsSource");
this.ClearBindings ("TableView");
this.ClearBindings ("TableView.Source");
this.ClearBindings (TableView);
this.ClearBindings ("TableView.Source.ItemsSource");
this.ClearBindings (set);
this.ClearBindings ("set");
this.ClearBindings ("Options");

TableView.ReloadData();

現在、アプリをロードすると、WeekSelectorView は ViewModel のデータに基づいてテーブルをロードします。ただし、バインディングをクリアしたいので、テーブルがまったくないはずです。

this.ClearAllBindings();

上記の行は機能しますが、すべてのバインディングをクリアしたくはありません。TableView の ItemsSource をクリアしたいだけです。


編集:

現在、.xib が関連付けられている WeekSelectorView があります。.xib には (他のユーザー コントロールの中でも) TableView があります。

私の WeekSelectorView は、ソースを独自のクラス「WeekSelectorTableSource」に設定します。この tablesource クラスは、ItemsSource バインディングに基づいて行/セクションの数を決定します。次に、いくつかのカスタム .xib セルを作成し、GetOrCreateCellsFor 内に

    protected override UITableViewCell GetOrCreateCellFor(UITableView tableView, NSIndexPath indexPath, object item)
    {
        var weekSelectorCell = WeekSelectorCell.Create();

        var set = _WeekSelectorView.CreateBindingSet<WeekSelectorView, WeekSelectorViewModel>();

        //Using string bindings since bindings with an index doesn't work  
        //ex: vm => vm.Options[indexPath.Row].Title
        set.Bind(weekSelectorCell).For(wc => wc.Title).To(string.Format("{0}{1}{2}", Options, indexPath.Row, Title)).OneWay();
        set.Bind(weekSelectorCell).For(wc => wc.Date).To(string.Format("{0}{1}{2}", Options, indexPath.Row, DateString)).OneWay();
        set.Bind(weekSelectorCell).For(wc => wc.Hours).To(string.Format("{0}{1}{2}", Options, indexPath.Row, TotalHours)).WithConversion(new HoursDecimalToHoursMinutesConverter(), null).OneWay();
        set.Apply();

        return weekSelectorCell;
    }

今、私がしたい理由はClearBindings()……

テーブルをリロードするたびに、以前のバインディングが保持されます。したがって、4 つのセルをそれぞれ 3 つのバインドでバインドすると、最初にアプリにセルに関連付けられた 12 のバインドが作成されます。テーブルをリロードすると (まだ 4 つのセルがある)、24 個のバインドが存在し、次に 36、48 などになります。

これが診断の一部です....

2013-07-16 16:26:03.950 FCXiOSv2[569:21e03] MvxBind: Warning: 1259.41 Weak Target is null in MvxWithEventPropertyInfoTargetBinding - skipping set
2013-07-16 16:26:03.951 FCXiOSv2[569:21e03] MvxBind: Diagnostic: 1259.41 Receiving setValue to Week
2013-07-16 16:26:03.952 FCXiOSv2[569:21e03] MvxBind: Warning: 1259.42 Weak Target is null in MvxWithEventPropertyInfoTargetBinding - skipping set
2013-07-16 16:26:03.953 FCXiOSv2[569:21e03] MvxBind: Diagnostic: 1259.42 Receiving setValue to 7/8/13 - 7/14/13
2013-07-16 16:26:03.954 FCXiOSv2[569:21e03] MvxBind: Warning: 1259.42 Weak Target is null in MvxWithEventPropertyInfoTargetBinding - skipping set

テーブルをリロードした後、このメッセージで洪水が発生しているだけなので、TableView.ReloadData().


編集:

よく考えて、Windows ネイティブ バインディングを扱っている同僚と話し合ったところ、自分が間違っていることがたくさんあることがわかりましたClearBindings(view)

一番外側のビューですべてのバインディングを処理していたので、ビューがリロードされても (つまり、テーブル内のセル)、一番外側のビューの割り当てが解除されていないため、バインディングは引き続き保持されていました。そのため、私のすべてのサブビューが独自のバインディングを処理することはありませんでした。これは大きな間違いでした。

これを修正するために(私が想像する「適切な」方法に)、カスタムセルに MvxTableViewCell を継承させ、遅延バインディングを追加しました。

public WeekSelectorCell (IntPtr handle) : base (handle)
{
    this.DelayBind (() => 
    {
        var set = this.CreateBindingSet<WeekSelectorCell, WeekViewModel>();
        set.Bind(DateLabel).For(lbl => lbl.Text).To(vm => vm.DateString);
        set.Bind(HoursLabel).For (lbl => lbl.Text).To(vm => vm.TotalHours).WithConversion(new HoursDecimalToHoursMinutesConverter(), null);
        set.Bind(TitleLabel).For(lbl => lbl.Text).To(vm => vm.Title);
        set.Apply();
    });
}

以前にこれを試しましたが、間にセットを作成しようとし、<WeekSelectorCell, WeekSelectorViewModel> (vm => vm.Options[ROW].Date) にアクセスしようとしましたが、これは常に失敗しました。私は最終的に、セットを作成する必要があることを<WeekSelectorCell, WeekViewModel>学びましOptions[]ObservableCollectionWeekViewModel

私が言ったように、要するに、私は使用する必要はありませんClearBindings(view)

4

1 に答える 1

3

ClearBindings() は MvvmCross でどのように機能しますか?

ClearBindings()ClearBindings(view)

それぞれMvxBindingContextが「バインディング」の 3 つの個別のリストを保持します。

  1. コンテキストで直接作成されたバインディングのリスト
  2. 子ビュー内で作成されたバインディングのビューベースのルックアップ テーブル - これらは現在、子ビューが親バインディング コンテキスト内で動的にインフレートされるときに Android バインディングでのみ使用されます。
  3. への最初の呼び出しを待機しているアクション (通常はバインディングの作成に進みます) のリストDataContext=value

これらの最初のものは、現在 iOS で使用されている主要なものであり、MvxBindingContextそのリストに対して公開されている唯一の公開された明確な API はClearAll.

2 番目のものは、一部の子ビューの Xml インフレーションのために Android でのみ使用ClearBindings(view)され、これらをそのために使用できるようにします。

これらすべての背後にある歴史は、特に Android と iOS の両方でのメモリ管理に関する多くの問題に関連しています。


ここで良いユースケースを掘り出すことができれば - 「これはいくつかのテスト目的のためだけのものです」から少し拡張されたもの - そして、ClearBindingsForObjector EnumerateBindingAPI は、拡張されたバインディングコンテキスト API と見なすことができるものになります - しかし、それは間違いなく必要になるでしょうAPI が実際に役立つものをプロジェクトが確実に把握できるようにするための、より強力な要件です。

それまでの間、必要に応じて tableView をルックアップとして使用してバインディングを作成および登録できると思います-たとえば、次のようなものです。

var bindings = MvxBindingSingletonCache.Instance.Binder.Bind(BindingContext.DataContext, tableView, "ItemsSource MySource");
this.RegisterBindingsFor(tableView, bindings);

それはあなたが呼び出すことができるようになりますClearBindings(tableView);


または、個々のバインディングの動作を停止したい場合はDispose、早い段階でそれを行うことができます-これにより、ソースバインディングがクリアされます-たとえば、次の場合:

    _myDisposableBindings = MvxBindingSingletonCache.Instance.Binder.Bind(BindingContext.DataContext, tableView, "ItemsSource MySource");
    this.AddBindings(_myDisposableBindings);

その後、後で次のようなことを行うことができます。

    foreach (var binding in _myDisposableBindings)
    {
        binding.Dispose();
    }
    _myDisposableBindings = null;

または、おそらくこれが私が行く方法です(ただし、ユースケースが何であるかによって異なります)-テーブルを独自のMvxViewコントロールに配置する方が簡単かもしれません-それはBindingContextあなたが呼び出すことができる独自のものを持つことができClearAllBindings()ます.

詳細については、 http://slodge.blogspot.co.uk/2013/06/n32-truth-about-viewmodels-starring.htmlMvxViewを参照してください。


最後に、バインディングをそのままにしておくことができるかどうかを検討することも検討しますが、その代わりにItemsSourceViewModel で をクリアすることができます。

于 2013-07-16T18:16:43.733 に答える