今天我有一个关于 Silverlight (4 RC) MVVM 和继承概念的特殊问题,并正在寻找最佳实践解决方案...我认为我了解 MVVM 背后的基本思想和概念。我的模型对ViewModel一无所知,因为ViewModel本身并不了解 View 。 ViewModel 知道模型, View 知道ViewModel。
想象以下基本(示例)场景(我试图让一切变得简短):
我的模型包含 ProductBase
具有一些基本属性的类,a SimpleProduct : ProductBase
添加更多属性和 ExtendedProduct : ProductBase
添加另一个属性。根据这个模型我有几个ViewModels,最重要的SimpleProductViewModel : ViewModelBase
和ExtendedProductViewModel : ViewModelBase
。最后但并非最不重要的一点是,根据 View SimpleProductView
和ExtendedProductView
。将来,我可能会添加许多产品类型(以及匹配的 View + 虚拟机)。
<强>1。收到模型集合时我如何知道要创建哪个 ViewModel?
调用我的数据提供程序方法后,它最终会得到 List<ProductBase>
。例如,它包含一个 SimpleProduct 和两个 ExtendedProducts。如何将结果转换为 ObservableCollection<ViewModelBase>
其中包含正确的 ViewModel 类型(一个 SimpleProductViewModel 和两个 ExtendedProductViewModel)?
我可能检查模型类型并相应地构造ViewModel,即
foreach(ProductBase currentProductBase in resultList)
if (currentProductBase is SimpleProduct)
viewModels.Add(
new SimpleProductViewModel((SimpleProduct)currentProductBase));
else if (currentProductBase is ExtendedProduct)
viewModels.Add(
new ExtendedProductViewModels((ExtendedProduct)currentProductBase));
...
}
...但我认为这是非常糟糕的做法,因为该代码不遵循面向对象的设计。相反,提供抽象工厂方法会将代码减少为:
foreach(ProductBase currentProductBase in resultList)
viewModels.Add(currentProductBase.CreateViewModel())
并且可以完全扩展,但由于模型不知道ViewModels,所以这是不可能的。我可能会在这里将界面引入游戏,但我还没有看到这种方法得到验证。
<强>2。选择 ViewModel 时如何知道要显示哪个 View?
这是同样的问题,但级别更高。最终终于得到了想要的ObservableCollection<ViewModelBase>
集合需要主视图为 ViewModel 选择匹配的 View。
在WPF中,有一个DataTemplate
可以在定义的数据类型上提供 View 的概念。不幸的是,这在 Silverlight 中不起作用,我找到的唯一替代品是 ResourceSelector
SLExtensions 工具包存在缺陷且不令人满意。
除此之外,问题 1 中的所有问题也适用。
Do you have some hints or even a solution for the problems I describe, which you hopefully can understand from my explanation?
提前谢谢您!
托马斯
最佳答案
我这样做是为了使 MVVM 成为强类型。
我定义了一些基本接口(interface)
public interface IModel
{
}
public interface IViewModel
{
}
public interface IViewModel<M> : IViewModel
where M : IModel
{
void Bind(M model);
}
public interface IView
{
}
public interface IView<VM> : IView
where VM : IViewModel
{
void Bind(VM viewModel);
}
这提供了我的模型、模型 View 和 View 之间的基本关系。
我为 IModel
创建抽象实现和通用IViewModel<>
& IView<>
接口(interface)。
public abstract class ModelBase : IModel
{
}
public abstract class ViewModelBase<M> : IViewModel<M>
where M : IModel
{
public abstract void Bind(M model);
}
public abstract class ViewBase<VM> : IView<VM>
where VM : IViewModel
{
public abstract void Bind(VM viewModel);
}
然后我使用它们来定义实际的具体对象 - 当然首先是接口(interface)。
public interface IPersonModel : IModel
{
}
public interface IPersonViewModel : IViewModel<IPersonModel>
{
}
public interface IPersonView : IView<IPersonViewModel>
{
}
注意接口(interface)的继承如何锁定类型关系。
现在可以定义具体的类了。
public class PersonModel : ModelBase, IPersonModel
{
}
public class PersonViewModel : ViewModelBase<IPersonModel>, IPersonViewModel
{
public override void Bind(IPersonModel model)
{
throw new NotImplementedException();
}
}
public class PersonView : ViewBase<IPersonViewModel>, IPersonView
{
public override void Bind(IPersonViewModel viewModel)
{
throw new NotImplementedException();
}
}
因此,给定一个模型,我可以寻找一个实现 IViewModel<M>
的对象对于该模型和给定的 View 模型,我可以查找 IView<VM>
对于该 View 模型。
这里可以使用依赖注入(inject)框架来进行查找。
我希望这会有所帮助。
关于Silverlight 与 MVVM 继承 : ModelView and View matching the Model,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2629579/