【问题标题】:Data binding without a ViewModel没有 ViewModel 的数据绑定
【发布时间】:2015-10-22 23:09:23
【问题描述】:

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

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

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

我可以使用一些很酷的技巧来构造一个 ViewModel,它可以包装任何 C# 模型类并发送属性更改事件,而无需知道模型类在运行时之前具有哪些属性?

我刚刚发现 DLR 和 DynamicObject 似乎很完美,但由于 Apple 的限制,它不适用于 Xamarin.iOS。

【问题讨论】:

  • 我也有类似的要求。我将动态数据存储为 JSON 对象。为了进行数据绑定,我将其转换为处理属性更改通知的 ObservableDictionary。在视图中,我创建了一个绑定集并手动将我的视图控件绑定到字典。它工作得很好。我不在电脑前,但我明天会发布一个示例。
  • 我认为如果问题中有一些具体的代码会更容易查看 - 实际查看/实验的东西。目前我不完全确定您的(视图)模型中的值发生了什么变化 - 它总是绑定 UI 控件,还是其他什么? (我不确定我是否了解您的更改通知将在哪里生成)
  • WPF 也尊重TypeDescriptors,因此您可以根据来自服务器的数据动态创建类型描述符。不知道邪恶的 ios 霸主是否压制了反射。

标签: dynamic mvvm mvvmcross inotifypropertychanged


【解决方案1】:

在没有戏弄DynamicObject 在 iOS 上的生活的情况下,想到的主要方法是:

  1. 您可以更改您的 web 服务生成代码,使其生成 INotifyPropertyChanged - 我使用过执行此操作的库 - 例如http://stacky.codeplex.com/SourceControl/latest#trunk/source/Stacky/Entities/Answer.cs - 如果您无法更改 Web 服务代码生成本身,您仍然可以使用某种 t4 或其他模板技巧来包装或篡改生成的代码。

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

  3. 您可以查看某种执行绑定的 valueconverter(或者 valuecombiner)——我可以很容易地想象一个 valueconverter,它接受一个包装的模型对象和一个字符串参数(属性名称)并将这两者一起使用(进行一些思考)来确定要做什么。我不确定这个如何与嵌套模型对象一起工作......但即使这样也是可能的......

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

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

【讨论】:

  • 很棒的反应。这些对我来说是很好的调查建议。我会将结果发回这里。
  • 我认为其中一个关键是定义更改机制(这可能与包装模型对象并将它们呈现为 ViewModels 的某些通用类相关联......)。怀疑它需要一些迭代才能变得好......但感觉有一些有趣的想法可以工作。期待看到你建造的东西(也许还有你必须扔掉的东西!)。玩得开心:)
【解决方案2】:

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

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

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

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

最后一个问题是如何在我的绑定表达式中绑定它。这就是[] 的用武之地。如果我的ObservableDictionary 属性名称被称为UserValues 并且它在键user1 处包含一个值,那么我可以使用2 方式绑定到它:UserValues[user1] 和所有内容似乎工作得很好。

我看到的一个问题是我现在要求我的动态数据源向我返回一个ObservableDictionary 而不仅仅是一个Dictionary。是不是要求太多了?

【讨论】:

  • 看起来我可以解决动态数据源的ObservableDictionary 要求,方法是使用我的ViewModel 包装我的Model 也用Model 包装一个普通的Dictionary一个ObservableDictionary。这样ViewModel 仍然使用ObservableDictionary,但Model 可以是普通的Dictionary
  • 相关示例代码:ObservableCollection used github.com/MvvmCross/MvvmCross-Samples/blob/… 并且 ObservableCollectionViewModel 用于此 ObservableCollectionView:github.com/MvvmCross/MvvmCross-Samples/blob/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-07
  • 1970-01-01
  • 1970-01-01
  • 2023-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多