【问题标题】:Silverlight with MVVM Inheritance: ModelView and View matching the ModelSilverlight 与 MVVM 继承:与模型匹配的 ModelView 和 View
【发布时间】:2010-04-13 12:47:15
【问题描述】:

今天我有一个关于 Silverlight (4 RC) MVVM 和继承概念的特殊问题,并正在寻找最佳实践解决方案……我认为我了解 MVVM 背后的基本思想和概念。我的 ModelViewModel 一无所知,因为 ViewModel 本身并不知道 ViewViewModel 知道 ModelViews 知道 ViewModels

想象一下以下基本(示例)场景(我尽量保持简短):

我的模型包含一个带有一些基本属性的ProductBase 类、一个添加更多属性的SimpleProduct : ProductBase 和添加另一个属性的ExtendedProduct : ProductBase。根据这个模型,我有几个 ViewModel,最重要的 SimpleProductViewModel : ViewModelBaseExtendedProductViewModel : ViewModelBase。最后但并非最不重要的一点是,根据意见 SimpleProductViewExtendedProductView。将来,我可能会添加许多产品类型(以及匹配的视图 + 虚拟机)。

1.收到模型集合时如何知道要创建哪个 ViewModel?
在调用我的数据提供者方法后,它最终会得到一个List<ProductBase>。例如,它包含一个 SimpleProduct 和两个 ExtendedProduct。如何将结果转换为具有正确的 ViewModel 类型(一个 SimpleProductViewModel 和两个 ExtendedProductViewModels)的ObservableCollection<ViewModelBase>

可能检查 Model 类型并相应地构造 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())

并且可以完美扩展,但由于 Model 不知道 ViewModels,这是不可能的。我可能会在这里将界面引入游戏,但我还没有看到这种方法得到证实。

2。选择 ViewModel 时如何知道要显示哪个 View?
这是几乎相同的问题,但在更高的层次上。最终获得所需的ObservableCollection<ViewModelBase> 集合将需要主视图为 ViewModel 选择匹配的 View

在 WPF 中,有一个 DataTemplate 概念,它可以根据定义的 DataType 提供 View。不幸的是,这在 Silverlight 中不起作用,我发现的唯一替代品是 SLExtensions 工具包的 ResourceSelector,它有问题且不令人满意。

除此之外,问题 1 中的所有问题也适用。

对于我描述的问题,你有一些提示甚至解决方案,希望你能从我的解释中理解?

提前谢谢你!

托马斯

【问题讨论】:

    标签: silverlight inheritance mvvm


    【解决方案1】:

    我这样做是为了让 MVVM 成为强类型。

    我定义了一些基本的接口

    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);
    }
    

    这提供了我的模型、模型视图和视图之间的基本关系。

    我为IModel 和通用IViewModel&lt;&gt;IView&lt;&gt; 接口创建抽象实现。

    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);
    }
    

    然后我使用这些来定义实际的具体对象 - 当然首先是接口。

    public interface IPersonModel : IModel
    {
    }
    
    public interface IPersonViewModel : IViewModel<IPersonModel>
    {
    }
    
    public interface IPersonView : IView<IPersonViewModel>
    {
    }
    

    注意接口的继承如何锁定类型关系。

    现在可以定义具体的类了。

    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&lt;M&gt; 的对象,给定一个视图模型,我可以为该视图模型查找IView&lt;VM&gt;

    这里可以使用依赖注入框架来进行查找。

    我希望这会有所帮助。

    【讨论】:

    • Enigmativity,非常感谢您的回复,我发现这个基于 MVVM 的接口实现非常有用。但最后,对我来说仍然存在差距......“Bind(IPersonModel模型)”的基本实现是什么样的,你能提供更多关于查找接口具体类的信息吗? (进一步阅读链接?)非常感谢您的支持!
    • (很快我就可以投票了,我还是 SO 新手,很难获得第一名 ;-))
    • Bind(IPersonModel model) 的实现会将模型存储在一个字段中,用作视图模型上与模型相关的属性的支持变量,并且还将设置所需的任何事件处理程序。对于视图,它还将用于设置与视图模型的实际绑定。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-06
    • 2015-03-16
    • 2022-06-24
    • 2013-10-21
    • 1970-01-01
    相关资源
    最近更新 更多