没有 ViewModel 的数据绑定

Data binding without a ViewModel

我正在做我以前从未尝试过的事情。我正在尝试创建动态 UI 并将其绑定到动态模型。换句话说,我的 Web 服务将发回我的 UI 的一个小元数据描述和要绑定到它的原始数据。因此,在构建时,我不知道 UI 我将构建什么,也不知道我的模型是什么。将它们绑定在一起似乎非常困难,如果不是不可能的话。

Mvx 允许我将 UI 直接绑定到一个模型,而无需它是 MvxViewModel。但是,如果我直接绑定到 Web 服务返回的模型,我将失去 RaisePropertyChanged() 的能力,因为它仅来自 MvxViewModel。

通常,我会编写一个包装模型的 ViewModel,并让所有包装的 setter 调用 RaisePropertyChanged()。但是,在这种情况下,我的模型是动态的,所以我无法在编译时用 ViewModel 包装它,因为直到运行时我才知道它是什么。

我可以使用一些很酷的技巧来构建一个 ViewModel,它可以包装任何 C# 模型 class 并在不知道模型 class 具有哪些属性的情况下发送 属性 更改的事件直到运行时?

刚刚发现了DLR和DynamicObject,看起来很完美,但是由于苹果的限制,无法在Xamarin.iOS上使用。

不逗DynamicObject进入iOS生活,想到的主要办法有:

  1. 您可以更改您的网络服务生成代码,以便它生成 INotifyPropertyChanged - 我已经使用了执行此操作的库 - 例如http://stacky.codeplex.com/SourceControl/latest#trunk/source/Stacky/Entities/Answer.cs - 如果您不能更改 Web 服务代码生成本身,您仍然可以使用某种 t4 或其他模板技巧来包装或扭曲生成的代码。

  2. 您可以研究将 Web 服务对象映射到某种可观察集合的某种代码(Kiliman 在评论中建议这样做)

  3. 您可以查看执行绑定的某种值转换器(或者可能是值组合器)——我可以很容易地想象一个值转换器接受一个包装模型对象和一个字符串参数(属性 name) 并同时使用这两者(经过一些反思)来确定要做什么。我不太确定这个如何与嵌套模型对象一起工作......但即使那样也是可能的......

  4. 您可以查看 MvvmCross 的某种自定义绑定扩展。这并不像听起来那么可怕,但确实需要一些反射技巧 - 要了解可能涉及的内容,请查看 FieldBinding 插件 - https://github.com/MvvmCross/MvvmCross-Plugins/tree/master/FieldBinding

    在实际的数据绑定过程中,插件将通过 IMvxSourceBindingFactoryExtension 调用 - 这将是您挂钩到其他一些自定义更改的机会 event(而不是 INotifyPropertyChanged ).可能需要做一些实验才能做到这一点......特别是如果你有嵌套对象(然后需要在绑定中“链接”)......但我认为应该可以通过这种方式产生一些东西。

我不确定我最终确定的是否支持所有可能的功能,但到目前为止,它似乎满足了我需要的一切。

我真的很喜欢自己编写 IMvxSourceBindingFactoryExtension 的想法。然而,在研究如何做到这一点时,我开始使用 MvvmCross 中已经存在的功能。我已经知道 MvvmCross 会尊重 ObservableCollection。我不知道的是我可以在我的绑定表达式中使用 [] 并且不仅整数索引器可以工作,而且 Dictionary 上的字符串索引器也可以。我发现 MvvmCross 示例代码在其 GIT 存储库中已经实现了 ObservableDictionary。事实证明,这就是我解决问题所需的全部内容。

所以我的模型包含静态属性和 ObservableDictionary<string,object> 动态属性,其中键是动态的名称 属性,值是 属性 的值。

我的 ViewModel 包装此模型 class 以发送 PropertyChanged 关于静态属性的通知。由于 Dictionary 的动态属性是可观察的,MvvmCross 已经处理了对该字典成员的更改,包括 2-way。

最后一个问题是如何在我的绑定表达式中绑定它。这就是 [] 出现的地方。如果我的 ObservableDictionary 属性 名称称为 UserValues 并且它在键 user1 处包含一个值,那么我可以 2-通过使用以下方式绑定到它:UserValues[user1] 一切似乎都运行良好。

我看到的一个问题是,我现在要求我的动态数据源 return 一个 ObservableDictionary 给我,而不仅仅是一个 Dictionary。是不是要求太高了?