Mvvm Windows Phone-在方法中创建ViewModels

Mvvm Windows Phone-在方法中创建ViewModels,mvvm,windows-phone-8,windows-phone,longlistselector,Mvvm,Windows Phone 8,Windows Phone,Longlistselector,我正在为数据库使用普通模型(实体),并将它们绑定到视图。这对我来说很好,但现在我有一个“特殊”的要求,我认为ViewModel是正确的方式 目前,我有一个包含许多项(1:n)的组模型。所有组都从数据库加载到ObservableCollection中,以在LongListSelector中显示它们。要求在LongListSelector中添加第二行,其中包含组中的当前项数。这不是很难,但我认为它是ViewModel的合适位置 我必须从组模型对象构建ViewModel,但正确的位置在哪里。我是否应该

我正在为数据库使用普通模型(实体),并将它们绑定到视图。这对我来说很好,但现在我有一个“特殊”的要求,我认为ViewModel是正确的方式

目前,我有一个包含许多项(1:n)的组模型。所有组都从数据库加载到ObservableCollection中,以在LongListSelector中显示它们。要求在LongListSelector中添加第二行,其中包含组中的当前项数。这不是很难,但我认为它是ViewModel的合适位置


我必须从组模型对象构建ViewModel,但正确的位置在哪里。我是否应该在页面的OnNavigatedTo中为每个组模型创建ViewModel对象?在本例中,我在页面的每个导航上创建ViewModel对象集合。还有其他方法吗?

在何处创建ViewModels有不同的方法。你用的是哪一种?在这种情况下,您应该遵循这些框架使用的说明和机制

如果您希望自己创建一个简单的VM并绑定它,那么您可以在不同的地方进行绑定。如果您只需要一个VM的一个实例,您可以在App.cs类中创建它,将其公开为public,以便您可以从应用程序的任何部分访问它。
如果您有多个不同的虚拟机,并且每个虚拟机负责一个视图,那么您可以将每个虚拟机的一个实例作为单个页面的一部分,仅当用户导航到该页面时才在代码中创建它。您还可以在XAML资源中创建VM实例,并从不同部分引用它们。目前还不清楚您的用例是什么,但这些是常见的解决方案。

这取决于具体情况。第一个问题是您将创建什么样的ViewModel类。我认为为每个页面创建一个ViewModel类是一个很好的约定,例如,对于
MainPage
您可以创建一个名为
MainPageViewModel
的类

MainPageViewModel
应负责从数据库加载数据,最好在其构造函数中加载。由于您必须使用项目计数扩展组,因此也可以为组创建一个名为
GroupViewModel
的ViewModel类,
MainPageViewModel
将具有一个名为groups of type
observeCollection
的属性

另一个有趣的问题是在哪里实例化
MainPageViewModel
?我看到三种不同的方法:

1直接在XAML中创建ViewModel 您可以在页面中创建ViewModel实例,并将其直接用作
DataContext
,如下所示:

<Page xmlns:local="using:MyApp">
    <Page.DataContext>
        <local:MainPageViewModel />
    </Page.DataContext>
...
</Page>
this.DataContext = new MainPageViewModel();
您可以在构造函数中执行此操作,即为每个页面实例创建一个ViewModel实例,也可以在OnNavigatedTo事件处理程序中执行此操作,即在用户每次导航到您的页面时创建一个新的ViewModel实例

这种方法有点灵活,但将代码放在页面的代码后面,这在纯MVVM中应该避免。然而,这个解决方案可能是最简单的

3 ViewModelLocator模式 最后一个解决方案最复杂,需要的代码最多,但在我看来也是最好的。
您需要一个类,其唯一目的是创建ViewModel实例,称为
ViewModelLocator
,它定义每个页面的ViewModel属性:

class ViewModelLocator
{
    MainPageViewModel MainPageViewModel
    {
        get
        {
            return new MainPageViewModel();
        }
    }
}
必须在App.xaml中将定位器的实例创建为静态资源:

<Application.Resources>
    <ResourceDictionary>
        ...
        <local:ViewModelLocator x:Key="ViewModelLocator" />
    </ResourceDictionary>
</Application.Resources>

...
然后,您可以简单地将此实例的属性绑定到页面上的DataContext:

<Page DataContext="{Binding MainPageViewModel, Source={StaticResource ViewModelLocator}}">
    ...
</Page>

...
这样,每次创建页面时,都会调用ViewModelLocator类的
MainPageViewModel
属性。在上面的示例中,我以每次创建一个新实例的方式实现了该属性,但是为了在每次情况下重用一个实例,可以很容易地对其进行修改


使用此模式,ViewModel实例的创建和管理与页面逻辑完全解耦,并且此解决方案是最灵活和可扩展的(例如,使用它实现设计时数据非常简单)。

我不知道正确的位置,因为我也不知道它是哪个ViewModel。LongListSelector位于主页面上,但它显示了组模型的列表,我希望将组中的项目数作为LongListSelector的第二行。那么它是一个MainViewModel还是一个GroupViewModel集合,以及何时、何处存储GroupViewModels集合?我已经有了一个MainViewModel,它可以从数据库加载这些组,并将它们存储在一个
ObservableCollection
中。如果创建GroupViewModel,是否需要为传输数据的模型的每个属性创建属性?当然可以,但这不是必需的。您可以在
GroupViewModel
中放置一个属性
groupwrappedgroup{get;set;}
,然后在XAML中通过该属性访问组类的属性,如下所示:
{Binding WrappedGroup.SomeProperty}
。好的!当我从数据库加载数据时,我有一个简单的模型组。我遍历所有组并创建一个GroupViewModel。组和项目也是如此,我创建了ItemViewModel,正确吗?是的,正确。同样,仅当您希望使用某种额外功能(计算属性等)扩展项目时,才无需为项目创建ItemViewModel类。好的,谢谢您的帮助!最后一个问题:我应该将DataContext(数据库)从MainViewModel传递到每个特定的ViewModel,还是应该将所有数据库内容(添加到datbase、删除…)保留在MainViewModel中?