4

ClearBindings()MvvmCross 中的工作如何?

至于测试目的,我只是想为 WeekSelectorView 清除 TableView 的ViewDidLoad()itemsSource。这是我尝试过的,但似乎没有任何效果。

(“this”指的是我当前的 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。


编辑:

我目前有一个 WeekSelectorView,它有一个 .xib 与之关联。在 .xib 中是一个 TableView(在其他用户控件中)。

我的 WeekSelectorView 将源设置为我自己的类“WeekSelectorTableSource”。此 tablesource 类根据 ItemsSource 绑定确定行/节的数量。然后它会在我的 GetOrCreateCellsFor 中创建一些自定义 .xib 单元格

    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 中使用的主要 API - 唯一公开的公开 API 为该MvxBindingContext列表公开的是ClearAll.

第二个仅在 Android 中用于某些子视图 Xml 膨胀 - 并ClearBindings(view)允许将这些用于此目的。

所有这些背后的历史都与许多 Android 和 iOS 内存管理问题密切相关——尤其是试图确保我们跟踪和处理所有绑定,包括在子视图、列表等中创建的绑定。


如果我们可以在这里挖掘出一个好的用例——从“这只是为了一些测试目的”稍微扩展一下——那么一个ClearBindingsForObjectEnumerateBindingAPI 将是可以考虑用于扩展绑定上下文 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()调用.

有关更多信息,MvxView请参阅http://slodge.blogspot.co.uk/2013/06/n32-truth-about-viewmodels-starring.html


最后,我可能还会考虑确定您是否可以只保留绑定,但可以ItemsSource在 ViewModel 中清除。

于 2013-07-16T18:16:43.733 回答