2015-10-05 82 views
0

我有一个与WPF和Prism相关的设计相关问题。我正在处理规则应用程序,我需要在TreeView控件中以分层方式显示不同类型的规则(模型)。我已经将Model的每个实例都包装在它们各自的ViewModel中并将其绑定到TreeView。下面我试图描述层次结构只是为了强调可以有多个相同类型的ViewModel,并根据它们的选择我需要相应地显示它们各自的视图。通过在WPF Prism中注入特定的ViewModel导航到视图

规则

---集团(GroupViewModel实例1)

------ X(XViewModel实例1)

---------ž (ZViewModel实例1)

------ X(XViewModel实例2)

---集团(GroupViewModel实例2)

------ Y(YViewModel实例1)

------ Z(ZViewModel实例2)

--------- X(XViewModel实例3 )

问题:

我需要一个机制来首先从TreeView中获取所选择的项目,然后用开放的导航到视图模型的视图(基于树的项目选择具有松散耦合)和饲料/注入在View中选择ViewModel。 需要获取选定ViewModel的代码示例,随ViewModel的注入一起导航到View?

目标:

我要找来处理在WPF这种情况与棱镜保持松耦合的一些最佳实践。

重要注意事项: TreeView显示在一个区域中,内容是另一个区域的一部分,我正在使用MEF DI容器。

回答

1

1)假设“执行”是某种业务逻辑,那么在模型类中使用它似乎是完全有效的。与验证同上。事实上,这可能是一个给定的,因为你正在寻找所有的业务逻辑和验证在一个地方。然后,该模型可能(可能)在将来重新使用,例如,如果您决定在现有模型之上开发基于Web的系统。事实上,我前一段时间是once asked a similar question

就我个人而言,我认为拥有一个“丰富”的模型类是很好的,包括实现INotifyPropertyChanged的属性,使其“具有约束力”。这是完全可以接受的,因为这个接口不在UI相关的框架名称空间(System.ComponentModel)中。为了方便起见,我甚至将ICommand属性包含在我的模型中,尽管它取决于您是多少“纯粹主义者”,模糊了模型定义和视图模型之间的界限。这导致你的第二个问题 - 通过拥有这样一个模型,它可以通过VM属性公开模型直接绑定到视图。

很多WPF开发人员似乎都编写基本上是模型类的镜像映像的VM类(包含所有与之相关的映射代码),但包括诸如INPC属性和ICommands之类的内容。这是我(个人)从未见过的大量开销。同样,关于如何使用模型和虚拟机,似乎有两个“阵营”,可能在某种程度上取决于应用程序需要如何“分层”。这很大程度上取决于个人偏好,而且像许多开发人员的挑战一样,我认为不存在正确或错误的方法。

关于3),是否要单击TreeView中的项目,导致在应用程序中的其他位置显示视图?我假设你正在使用依赖注入框架? AFAIK棱镜区域经理需要这一点,我不知道如何在没有DI框架的情况下使用区域管理器。

首先,您需要定义在一个区域中显示该视图,例如: -

<ContentControl Regions:RegionManager.RegionName="MyRegionName" /> 

要显示的区域的视图使用棱镜区域经理: -

_regionManager.RequestNavigate("MyViewName", "MyRegionName"); 

当您使用DI框架注册视图时,将分配视图名称,例如这是如何在温莎城堡完成: -

Container.Register(Component.For<MyView>().ImplementedBy<MyView>().LifeStyle.Transient.Named("MyViewName")); 

希望这会让你在你的路上。 Prism导航有很多,尤其是让你的头脑看到生命周期。另外,通过导航视图的虚拟机来实现INavigationAware以便它可以对事件作出反应通常是有用的。被导航到/从。

编辑(基于OP编辑):

你还没有说,该地区是在同一个视图树视图。如果是这样,那么你可以在没有棱镜导航的情况下实现这一点。 “主” VM(涉及到TreeView的观点)可能使当前选定规则的虚拟机,你可以绑定到ContentControl中(当然是一个INotifyPropertyChanged的属性!):

<ContentControl Content="{Binding SelectedRule}" /> 

然后,它只是一个案例该规则的虚拟机设置的DataTemplates: -

<DataTemplate DateType="{x:Type XRuleViewModel}"> 
    ... XAML ... 
</DataTemplate> 

由于TreeView的选择变化,ContentControl中会结合相应的规则VM,以及相应的DataTemplate将呈现所需的内容。

如果区域在单独的视图中,那么您将需要使用棱镜导航。这里的问题是你需要导航的视图名称,但是你的“主”(TreeView)虚拟机不知道视图,只有规则虚拟机。一个简单的选项可能是在规则虚拟机上拥有一个公开相关视图名称的属性。如果您更喜欢纯粹主义者,并且希望将这些知识保留在虚拟机之外,那么您可以实现一种机制,将所有规则虚拟机与其相应的视图名称(例如,在应用程序启动期间)一起注册。这可以像Dictionary一样简单。在TreeView中选择规则VM时,您只需查找在RequestNavigate()调用中使用的相应视图名称即可。

+0

感谢您的回答,但我仍然无法获得积分。 3.我知道区域和导航到View使用相同的技术,但问题是,我如何指示我的视图显示基于TreeView选定项目的特定ViewModel。是的,我在棱镜中使用MEF DI。 –

+0

@FSX,所以你想显示一个特定的视图,取决于你点击了哪个treeview项目?这个视图在哪里出现 - 作为与树视图相同的窗口内的内容,还是其他内容? –

+0

看到我上面编辑的问题更多的细节和澄清 –

1

@Andrew在正确的轨道上。首先,除非你的架构绝对需要它,否则不需要将模型包装在ViewModel中。其中,我猜可能没有。完成此任务的最简单方法是使用InvokeCommandAction来响应所选项目更改事件。然后执行一个将导航到所需视图的命令。使用选定的tem作为参数来确定您要查找的视图。在您导航时,您还可以使用NavigationParameters将所选项目作为参数传递,并在目标上使用INavigationAware以便在OnNavigatedTo方法中获取该参数。

相关问题