我注意到在 v3 中,MvvmCross 删除了通用声明<TViewModel>
,MvxTouchViewController
并将其重命名为MvxViewController
.
这意味着该ViewModel
属性被键入为通用接口IMvxViewModel
而不是特定的TViewModel
.
如果我需要TViewModel
在我的视图控制器中访问,是否有一种方便的方法可以让 ViewModel 已经转换为此视图的特定实例类型?还是我每次都必须自己投?
我注意到在 v3 中,MvvmCross 删除了通用声明<TViewModel>
,MvxTouchViewController
并将其重命名为MvxViewController
.
这意味着该ViewModel
属性被键入为通用接口IMvxViewModel
而不是特定的TViewModel
.
如果我需要TViewModel
在我的视图控制器中访问,是否有一种方便的方法可以让 ViewModel 已经转换为此视图的特定实例类型?还是我每次都必须自己投?
以前基于通用的 MvvmCross 视图已从 MvvmCross 中删除,主要是因为基于目标 C 的平台中的“Heizenbugs”威胁。
对于很少有人知道的内容Heizenbugs
,请参阅http://forums.xamarin.com/discussion/771/exporting-generic-type-to-objc-supported
我不相信我见过 Heizenbug,但 Xamarin 在他们的建议中非常明确地建议不惜一切代价避免它们 - 例如,他们两次更改编译器以为我们的泛型发出错误。事实上,在 .Mac 上,这样的通用代码今天仍然是一个错误,而在 .iOS 上,它只是一个非常可怕的警告。
除此之外,我们在从通用基类继承时也确实遇到了一些基于 Xaml 的平台的问题——尽管这些问题主要得到了解决(例如,当我从通用基类继承页面时出现 XamlParseException)
(除此之外 - 为了允许一些向后兼容性,WindowsPhone 仍然有一些有限的通用视图支持,但这被标记为Obsolete
,我很遗憾允许它继续存在......)
好消息是,根据我的经验,大多数 View 不需要知道它们的 ViewModel 类型——相反,大多数 View 可以使用“纯绑定”构建而无需声明类型化的 ViewModel。
对于那些确实需要知道其 ViewModel 类型的剩余视图,然后一个简单的添加属性可以快速添加它 - 例如:
protected MyViewModel MyViewModel
{
get { return (MyViewModel)base.ViewModel; }
/* set is optional - not typically needed
set { base.ViewModel = value; }
*/
}
或者,如果您愿意,您可以为此编写扩展方法 - 例如:
public static TViewModel TypedViewModel<TViewModel>(this IMvxView view) where TViewModel : class, IMvxViewModel
{
return view.ViewModel as TViewModel;
}
非常另类....
.... 如果您不怕鬼、妖精或Heizenbugs
....
将TypedViewModel
属性添加到所有视图的一种方法是将泛型添加回视图层次结构 - 这对你来说很容易 - 例如在 Android 中添加
public class BaseActivity<TViewModel> : MvxActivity
where TViewModel : class, IMvxViewModel
{
protected TViewModel TypedViewModel
{
get { return (TViewModel)base.ViewModel; }
/* set is optional - not typically needed
set { base.ViewModel = value; }
*/
}
}
这对你来说应该很好......但是如果你碰到了一个 Heizenbug,那么我认为没有人能够帮助你。Xamarin 非常明确地反对这种模式——尤其是在基于 objC 的平台上。
从 3.5 开始,再次支持基于通用的视图,因为显然底层 Xamarin 问题已得到修复。
http://slodge.blogspot.co.uk/2015/01/mvvmcross-v35-pushed-to-stable.html