2015-10-22 43 views
2

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

MVX让我可以直接绑定UI的模型,而它作为一个MvxViewModel。但是,如果我直接绑定到由Web服务返回的Model,则我失去了RaisePropertyChanged()的功能,因为它只来自MvxViewModel。

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

有一些很棒的技巧我可以用它来构造一个视图模型,它可以包含任何C#模型类,并发送属性更改事件,不知道是什么属性的模型类具有直到运行时?

我刚刚发现的DLR和这似乎是完美的DynamicObject,但由于苹果的限制,它不会在Xamarin.iOS工作。

+1

我有类似的要求。我将我的动态数据存储为JSON对象。对于数据绑定,我将其转换为处理属性更改通知的ObservableDictionary。在视图中,我创建了一个绑定集并手动将我的视图控件绑定到字典。它工作得很好。我不在我的电脑,但我明天会发布一个样本。 – Kiliman

+0

我认为如果问题中存在一些具体代码 - 实际查看/实验的内容,则可以更轻松地查看此问题。目前我不完全确定什么改变了你的(视图)模型中的值 - 它总是绑定UI控件,还是其他东西? (我不确定是否知道您的更改通知将生成在哪里) – Stuart

+0

WPF也尊重[TypeDescriptors](https://msdn.microsoft.com/en-us/library/system.componentmodel.typedescriptor(v = vs。 110).aspx),因此您可以根据服务器的数据动态创建类型描述符。不知道这些邪恶的ios overlords是否会阻止反射,tho。 – Will

回答

2

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

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

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

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

最后一个问题是如何在绑定表达式中绑定它。这就是在[]进来如果我ObservableDictionary属性名称叫做UserValues,它包含在关键user1的值,那么我可以2路绑定到它通过使用:UserValues[user1],一切似乎很好地工作。

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

+1

它看起来像我可以通过使用我的'ViewModel'来解决动态数据源的'ObservableDictionary'需求,该''ViewModel'封装了我的'Model'以在'Model'中封装一个普通的'Dictionary'与'ObservableDictionary '。这样''ViewModel'仍然使用'ObservableDictionary',但'Model'可以是一个普通的'Dictionary'。 – scastria

+0

相关示例代码:使用ObservableCollection https://github.com/MvvmCross/MvvmCross-Samples/blob/6f702e5ba595b345db4366a074903a8f234f5081/ApiExamples/ApiExamples.Core/ViewModels/ViewModels.cs#L203并在此ObservableCollectionView中使用ObservableCollectionViewModel:https:/ /github.com/MvvmCross/MvvmCross-Samples/blob/6f702e5ba595b345db4366a074903a8f234f5081/ApiExamples/ApiExamples.Ios/Views/FirstView.cs#L224 –

2

没有戏弄DynamicObject到生活在iOS上,即认为主要方法是:

  1. 你可以改变你的web服务生成的代码,以便它产生INotifyPropertyChanged - 我用的是做到这一点的库 - 例如http://stacky.codeplex.com/SourceControl/latest#trunk/source/Stacky/Entities/Answer.cs - 如果您无法更改Web服务代码生成本身,您仍然可以使用某种t4或其他模板技巧来封装或变换生成的代码。

  2. 你可以调查某种代码,Web服务对象,以某种观察到的集合的映射(Kiliman曾建议这评论)

  3. 你可以看一下某种valueconverter的(或可能valuecombiner)绑定 - 我可以很容易想象一个valueconverter,它需要一个包装模型对象和一个字符串参数(属性名称),并将这两个参数一起使用(通过一些反射)来确定要做什么。我不太确定这个如何与嵌套的模型对象一起工作......但即使这样做也是可能的......

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

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

+0

真棒回应。这些对我来说是很好的建议。我会在这里回复我的结果。 – scastria

+0

我认为其中的一个关键是定义了变化机制(它可能与一些可能包含Model对象的Generic类绑定,并将它们呈现为ViewModels ...)。怀疑它会需要一些迭代才能获得好的效果......但感觉有一些有趣的想法可以奏效。期待看到你建立的东西(也许还有你必须扔掉的东西!)。玩得开心:) – Stuart