WPF棱镜-使用棱镜区域有什么意义?

WPF棱镜-使用棱镜区域有什么意义?,wpf,design-patterns,prism,prism-4,Wpf,Design Patterns,Prism,Prism 4,我只是想知道区域的意义是什么。我想我不明白他们解决的问题 例如,我看到很多人使用regions作为导航区域,但为什么不将ItemsControl绑定到ObservableCollection,而不是使用region并将不同的导航元素加载到该区域 与替代品相比,it的使用/好处的真实例子会让人震撼 区域启用的场景 为了得到答案,我浏览了这篇文章: 据我所知,Region功能的设计目的是在既不是视图也不是视图模型的代码中启用视图注册/注入 以ContentPresenter控件为例。如果使用它而不

我只是想知道区域的意义是什么。我想我不明白他们解决的问题

例如,我看到很多人使用regions作为导航区域,但为什么不将ItemsControl绑定到ObservableCollection,而不是使用region并将不同的导航元素加载到该区域



与替代品相比,it的使用/好处的真实例子会让人震撼

区域启用的场景

为了得到答案,我浏览了这篇文章:

据我所知,Region功能的设计目的是在既不是视图也不是视图模型的代码中启用视图注册/注入

ContentPresenter
控件为例。如果使用它而不是区域,则视图模型必须返回具体的视图,以便使主视图与其子视图不可知

如果使用
ItemsControl
并将其绑定到视图模型上的任意数据,则需要在主视图的DataTemplate中指定要实例化的视图

使用区域,可以将视图注册到容器中的区域。视图和相应的视图模型都不需要知道运行时将使用的具体视图的任何信息。它将由容器注入

这样,您就可以将主视图与其子视图完全解耦,而不必强制视图模型了解这些子视图

具体用例

我不确定这有多有用,以及这将实现哪些具体场景。我使用了带有插件架构的
ContentPresenter
,但我不确定它是否适合这个模型。对于插件模型,您希望视图和视图模型绑定在一起,因此这种方法不会为您带来任何好处

我想,如果你发现自己有很大的不相关的观点,并且想把它们分开,那就最好了。通过一次只注入视图和视图模型的一部分,它可能有助于将集成测试彼此隔离


我正在抓取令人信服的真实世界用例的稻草:)在几乎所有的情况下,您都可以简单地使用
用户控件
,并且可以放弃整个动态注册的事情,没有真正的缺点。

区域允许您在程序中定义一个为特定目的而存在的点。例如,您可能有一个菜单区域或页脚区域。然后,可以将这些特定区域的视图/视图模型分离到程序的各自部分中

因此,与其让
ApplicationViewModel
包含
MenuViewModel
FooterViewModel
的属性,并让视图将每个部分绑定到这些属性,不如让菜单和页脚有单独的视图模型,而ApplicationViewModel只处理内容。这是在应用程序中分离一些逻辑边界的更好方法


就我个人而言,我认为这些地区被过度使用和滥用得可怕。我几乎从不使用它们,除非我有一个与我的应用程序代码的其余部分无关的页眉或页脚之类的东西。它们也主要用于View First开发,我更喜欢ViewModel First。

将RegionManager与EventAggregator进行比较,您将看到它的优势

EventAggregator允许不同组件发布/订阅事件,而无需彼此耦合。区域管理者也是如此。。。您可以将一个视图加载到区域中,而另一个视图不知道其中发生了什么。它使您的视图彼此分离。。。这并不是说每个视图都应该彼此不知道。。。有时一个视图应该知道另一个视图


看看Microsoft Outlook(注意:我在这里编造东西,包括名字,因为Outlook不是用WPF编写的,而是用C++):

主UI将具有以下区域:

  • MenuRegion
  • 导航区
  • 内容区
  • 边区
区域是在标准控件(因此您仍然需要标准控件)上定义的,更具体地说,是项控件、内容控件和开箱即用的选择器(您可以扩展其他控件以支持“区域”)。它们允许另一段代码通过解析并将适当的视图加载到这些区域来管理这些区域。基本上,保持事物的解耦

您的主UI不需要了解应用程序的所有信息;相反,它只需要知道它有一个菜单、导航、内容和侧区。实际放置在区域中的视图并不重要。现在,这并不意味着每个视图都应该彼此解耦。我以后再谈

那么,它实际上是如何解耦的呢?下面是一个场景:单击导航控件中的日历图标。那么当你这么做的时候会发生什么呢

  • NavigationView
    -按钮(图标)绑定到
    ICommand
    ,因此它调用
    ExecuteLoadCalendar()
    函数
  • NavigationViewModel
    -函数
    ExecuteLoadCalendar()
    使用
    EventAggregator
    宣布用户正在尝试启动日历
  • ContentController
    -
    ContentController
    已订阅了
    LoadCalendarAggregateEvent
    ,因此将执行该操作。在这里,它使用
    IRegionManager
    和区域名称解析/激活
    CalendarView
    COUPLED)。它应该通过抓取
    ICalendarView
    而不是
    CalendarView
    来实现这一点
  • 在整个过程中,除了
    ContentController
    CalendarView
    /
    ICalendarView
    之外,每个部分都是解耦的。当然,你可以说
    [Export("Calendar")]
    public class CalendarView : UserControl, ICalendarView { }