MVVM,构建View的最佳方式

时间:2013-06-21 08:05:46

标签: wpf mvvm

我已经为我的应用程序创建了一个根AppView,一个根AppViewModel作为所有东西的容器。在应用程序视图中,我有一个TabControl,每个选项卡都有自己的任务。一个用于汇总数据的选项卡,一个用于发布的选项卡,一个用于管理的选项卡等:

App_View[Model] // root
{ 
   TabTask1_View[Model], TabTask2_View[Model], TabTask3_View[Model] // tab items
} 

1)在MVVM中,我将整个视图和视图模型分组到主应用程序视图和应用程序模型视图中是否标准?

2)在MVVM中,应该为每个视图实现模型。 vm?或者,如果我将整个模型实现为一个或两个类文件并在它们之间共享模型,它是否是标准的?我个人认为模型部分并不特定于某个视图,例如可以在代码中的任何位置使用的类“学生”,并且不限于某个视图。基于此,如果模型是通用的并且是共享的,那么遵循命名约定Class +'Model'是否合适呢?像StudentModel?在普通或共享类名称之后添加'Model'是否有用/必要,就像我说的那样?

3)在WPF中,实现视图的最佳方法是什么?我想非常容易地编辑和设计,没有任何限制,它应该足够标准以满足未来的需求。有4种用法:Window,Page,UserControl和DataTemplate。哪一个是你最好的选择? UserControl或Page?

4)在WPF中,如何在运行时基于MVVM方法在tabItem中动态加载UserControl / Page(View)?

3 个答案:

答案 0 :(得分:2)

你是在作弊。这是4个问题!

1)

就如何对View和Viewmodel进行分组而言,我看到人们将视图和视图模型放在同一个命名空间/文件夹中,而其他人则根据功能将它们分成不同的文件夹。最适合您的选择是适合您/您的团队。没有“正确”的方式。

2)

保持干燥 - 所以不要重复自己。重用代码是完全合理的。如果你有共同的课程,请保持共同。至于命名,类的名称应该有助于解释它的作用:我相信你能够弄清楚NavigationService,NavigationMenuItem和NavigationMenuView这些类做了什么,并且可能可以组合一个良好的心理模型如何他们有关系。所以 - 如果命名一个类BlahViewModel或BlahModel对你有用,那就去做吧。

3)实施观点:

窗口始终独立显示。页面旨在用于导航应用程序(通常使用后退和前进按钮,例如Internet Explorer)。页面必须托管在NavigationWindow或Frame中。如果您正在寻找动态添加/删除内容,向ItemsControls添加内容(TabControl等),那么您将需要创建用户控件。您可以将用户控件放在Page和Window对象中,放到其他控件等中,并且确实是WPF开发人员的主力。

4)

这里有很多选择:

1)快速而肮脏的方法是创建DataTemplate,在给定类型为X的ViewModel时,加载并将ViewModel应用于其数据上下文。这将允许您将ViewModel直接注入控件并具有正确的View渲染。

一个例子:

View.xaml

<ContentControl Content="{Binding Error, Mode=OneWay}" />

视图模型:

        private void ReceiveError(ErrorViewModel errorModel)
        {
            //if (errorModel.AcceptCommand==null || errorModel.AcceptCommand is NoOpCommand)
            errorModel.AcceptCommand = new DelegateCommand(ClearError);
            Error = errorModel;
        }
public ErrorViewModel Error
        {
            get { return _error; }
            set
            {
                _error = value;


                _propertyChangedHelper.NotifyPropertyChanged(this, () => Error);
            }
        }

Styles.Xaml(ResourceDictionary)

<DataTemplate DataType="{x:Type vm:ErrorViewModel}">

        <DataTemplate.Resources>
            <conv:CustomisableBooleanToVisibilityConverter x:Key="VisibilityConverter" TrueValue="Visible" FalseValue="Collapsed" />
        </DataTemplate.Resources>
        <Popup AllowsTransparency="True" PopupAnimation="Fade" Placement="Center"  StaysOpen="True"
               PlacementTarget="{Binding Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type v:ModuleView}}}"
               IsOpen="True" Width="400" SnapsToDevicePixels="True"/>

所以你可以看到我将我的viewmodel直接注入到内容控件中,它使用绑定到viewmodel类型的数据模板来查找它的视图。

2)

更好的选择是使用DataTemplateSelector。这基本上允许您指定哪些模板可用于控件,然后使用您编写的逻辑来确定要使用的数据模板。您可以找到此here的示例。

3)

使用抽象UI控件的框架。微软有一个框架(免费),称为Prism。基本上,不是将用户控件直接添加到TabControl,ItemsControl等,而是将控件添加到命名的“Region”。此区域映射到基础控件,并且适配器用于管理在您要求时添加/删除UserContorl的方式。您可以找到对此here的深入讨论。但要注意,Prism是一个应用程序框架,因此实现这个不是3个小时的工作。

答案 1 :(得分:1)

这不是一个答案,这是我的经验,我将向您解释以及我如何处理MVVM。我从3个月前开始使用WPF,然后处理它。

  1. 对于每个新主题/ menue /选项,我创建一个包含ViewModel和Views的新项目文件。所有Business类都收集在一个Project文件中,因为我可能必须在多个ViewModel中使用它。

  2. 是的,作为初学者,我有必要为这些类命名... ViewModel和..View。它让我很容易将差异分开,并且更容易向其他人解释你的课程(例如,如果你的编码有问题)

  3. 我正在使用UserControls来获取不同的视图,我将它们加载到ContentControls和TabControls中没有任何问题。

  4. 看看Prism的MVVM模式。

答案 2 :(得分:1)

第1点:

这取决于。 AFAIK有两种广泛使用的方法。首先,正如您所说的那样,将所有具有直接依赖关系的Window组成的VM组合在一起,形成一个显示实际程序结构的类结构。其次是使用EventAggregator(Prism)/ Messenger(MVVM Light)松散地链接VM而不是直接依赖的地方。

现在两种方法都有其好处

  • 使用第一个很容易识别您的程序结构,因为您的VM依赖关系清楚地显示了它,从第二种方法可以清楚地看到它。
  • 第二种方法在单元测试虚拟机时可以帮助你很多,你不需要模拟/解决所有依赖虚拟机的问题,它还有助于在改变项目结构时对代码进行重新分解(想想“插件”)类)
哦,这些^^绝不是排他性的。你可以很好地混合这些。

第2点:

模型没有任何推荐的1&lt; - &gt; 1与View / VM的关系,如View与VM的关系。模型只保留您的业务逻辑。我有应用程序,有时根本不持有模型。有些东西只有整个应用程序使用的模型(当后端是一个c ++库而你只是用C ++ / CLI模块与它连接时)。是保持命名约定以使用“Model”

附加Model类名

第3点

所有这些怎么样?适用时使用它们。不要偏爱任何人。当一个视图组成多个其他部分时,这些部分本身就是一个带有虚拟机的视图,我有一个DataTemplate,数据为UserControl。您的应用几乎总是使用一个窗口,我认为Page对于基于导航的应用非常有用。认为Page是我用过的最少的东西。

第4点

这是教程的问题。举几个例子,看看它是如何实现的,推理它并选择你的方法。如果您使用VS2010获得MVVM In the box(这很棒。没有2种方法。真的希望这可以为VS2012更新,如果它还没有)。对于VS2012,请查看显示该概念的Two Views MVVM CodeProject,然后您可以将其应用于您选择的任何ItemsControl

最后,至少在你启动时,从使用MVVM助手库开始。我更喜欢MVVM Light&lt; - 该链接有几个视频,图书馆的作者显示了一些用法,你可以在这里找到关于它的大量帮助。如果您想自己做事,从中学习基础知识,然后自己实施。如果从第一天起走高速路,这只是一个更长的学习曲线(仅限我的意见)