在表示逻辑层 (PLL) 中,我有所谓的“视图模型”类,它们实现在业务逻辑层 (BLL) 中定义的 /extend 接口,如下所示:
namespace BLL.Abstract.POCO
{
// also implemented in data access layer (DAL) by data model entities
public interface ISomeDomainModelEntity
{
string Name { get; set; }
string Description { get; set; }
}
}
namespace PLL.Abstract.ViewModels
{
public interface ISomeDomainModelEntityViewModel
: ISomeDomainModelEntity, INotifyPropertyChanged
{
bool IsSelected { get; set; }
}
}
namespace PLL.Concrete.ViewModels
{
public class SomeDomainModelEntityViewModel
: ViewModelBase, ISomeDomainModelEntityViewModel
{
private string _name;
private string _description;
private bool _isSelected;
public string Name { get { return _name; } set { _name = value; NotifyPropertyChanged(() => Name); } }
public string Description { get { return _description; } set { _description = value; NotifyPropertyChanged(() => Description); } }
public bool IsSelected { get { return _isSelected; } set { _isSelected = value; NotifyPropertyChanged(() => IsSelected); } }
}
}
请注意,这ViewModelBase
是一个允许这种花哨的强类型INotifyPropertyChanged
实现的抽象类。
上述实现的IsSelected
属性显然只需要在表示层中(可视化几十个这样的对象显示在一个列表中,ItemTemplate
其中一个特性 aListBox
将其IsChecked
属性绑定到IsSelected
),并且表示逻辑在返回业务之前知道如何使用它逻辑层。
我遇到的问题是,我发现名称“ViewModel”与此冲突:
namespace PLL.Abstract.ViewModels // hmmm...
{
public interface ISomeWindowViewModel
{
ObservableCollection<ISomeDomainModelEntityViewModel> SomeItems { get; }
}
}
的实现ISomeWindowViewModel
最终分配给视图的DataContext
属性:
namespace PLL.Concrete.ViewModels
{
public class SomeWindowViewModel : WindowViewModelBase, ISomeWindowViewModel
{
private readonly ObservableCollection<ISomeDomainModelEntityViewModel> _items;
public SomeWindowViewModel(IView view, ObservableCollection<ISomeDomainModelEntityViewModel> items)
: base(view)
{
_items = items;
}
public ObservableCollection<ISomeDomainModelEntityViewModel> SomeItems { get { return _items; } set { _items = value; } }
}
}
namespace PLL.Abstract
{
public abstract class WindowViewModelBase : ViewModelBase
{
public IView View { get; private set; }
protected WindowViewModelBase(IView view)
{
View = view;
View.DataContext = this;
}
}
}
这是我在阅读 Mark Seeman 的.NET 中的 Dependency Injection 中关于如何将 DI 应用于 WPF 之后开始进行重大重构的结果(到目前为止读得很好,尚未完成),虽然起初它似乎有点倒退到将 View 实现注入到 ViewModel 中,我可以通过处理视图的显示和关闭来欣赏获得的控制/简单性。在重构之前,我有一个带有 BLL 的工作应用程序,它与 DAL 和 PLL 紧密耦合;现在 BLL 没有任何依赖关系,这太棒了。
我仍在重新配置组合根(使用 Ninject.Extension.Conventions),所以在一天结束时,我可能会意识到我需要进行一些调整以使其全部正常工作......并且它可能会受伤,但我已经准备好了!
所以问题如下:
- 我觉得我的接口太多了,但是我完全不喜欢使用约定的 DI 配置(嗯,完全绿色的 DI!);当类型实现接口时,按惯例配置 IoC 容器似乎要容易得多……但这是否有点矫枉过正?
- 这里是否过度使用了“ViewModel”这个术语?或者更确切地说,“ViewModel”和“WindowViewModel”之间的区别是有保证的还是我遗漏了什么?ViewModel “包含”其他 ViewModel 是否正常?如果没有,是否可以为在视图中用作 DataContext 的 ViewModel 提供一些“WindowViewModel”名称?
- 这里是否有任何明显的架构缺陷最终会导致代码库变得一团糟?这个想法是尽可能可靠地使用 DI 实现 MVVM,但我认为我还有很多东西要学习。
- 去年的这个问题在我输入这篇文章时出现在“类似问题”列表中,并且真的开始在我的脑海中进一步模糊 - 接受的答案和其他评论与我最近一直在阅读的内容完全矛盾。具体来说,应该为 ViewModel 类注入一些 IView 实现 - 这个问题/答案+评论的说法正好相反,这就是我最初所拥有的(注入了一些 IViewModel 实现的 View)。看起来这两种方式都是完全可以接受的,这只是个人喜好的问题?