【问题标题】:Windows Phone - Create ViewModels within methodWindows Phone - 在方法中创建 ViewModel
【发布时间】:2013-06-10 19:40:46
【问题描述】:

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

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

我必须从组模型对象构建 ViewModel,但正确的位置在哪里。我应该为页面的 OnNavigatedTo 中的每个组模型创建 ViewModel 对象吗?在这种情况下,我会在每次导航到页面时创建 ViewModel 对象集合。还有其他方法吗?

【问题讨论】:

    标签: mvvm windows-phone-8 windows-phone longlistselector


    【解决方案1】:

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

    这个MainPageViewModel 应该负责从数据库加载数据,最好是在它的构造函数中。由于您必须使用项目计数来扩展您的组,因此您也可以为您的组创建一个 ViewModel 类,称为 GroupViewModel,而 MainPageViewModel 将有一个名为 Groups 的属性,类型为 ObservableCollection<GroupViewModel>

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

    1 直接在 XAML 中创建 ViewModel

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

    <Page xmlns:local="using:MyApp">
        <Page.DataContext>
            <local:MainPageViewModel />
        </Page.DataContext>
    ...
    </Page>
    

    我认为这可能是最糟糕的解决方案,因为它需要 ViewModel 有一个无参数构造函数(这种情况很少发生),而且它非常不灵活 ,您无法控制何时创建 ViewModel 实例。

    2 在后面的代码中实例化 ViewModel

    您可以像这样在代码中简单地创建 ViewModel 实例:

    this.DataContext = new MainPageViewModel();
    

    您可以在构造函数中执行此操作 - 这样将为每个 Page-instance 创建一个 ViewModel-instance - 或在 OnNavigatedTo 事件处理程序中 - 这样每次用户导航到时都会创建一个新 ViewModel-instance你的页面。

    这种方法更灵活一些,但是将代码放在页面后面的代码中,这在纯 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 实例的创建和管理与页面逻辑完全解耦,这种方案是最灵活和可扩展的(例如实现设计时数据真的很简单和它)。

    【讨论】:

    • 我已经有一个 MainViewModel,它从数据库中加载组并将它们存储在 ObservableCollection&lt;Group&gt; 中。如果创建 GroupViewModel,是否需要为传输数据的模型的每个属性创建一个属性?
    • 当然可以,但没必要。您可以在GroupViewModel 中放置一个属性Group WrappedGroup { get; set; },然后在XAML 中通过该属性访问Group 类的属性,如下所示:{Binding WrappedGroup.SomeProperty}
    • 好的!当我从数据库加载数据时,我有一个简单的模型组。我遍历所有组并创建一个 GroupViewModel。组和项目再次相同,我创建了 ItemViewModel,是否正确?
    • 是的,没错。同样,没有必要为你的项目创建一个 ItemViewModel 类,只有当你想用某种额外的功能(计算属性等)扩展它们时。
    • 好的,谢谢您的帮助!最后一个问题:我应该将 MainViewModel 中的 DataContext(数据库)传递给每个特定的 ViewModel,还是应该在 MainViewModel 中保留所有数据库内容(添加到数据库、删除...)?
    【解决方案2】:

    在哪里创建 ViewModel 有不同的方法。你在使用popular MVVM frameworks中的任何一个吗?在这种情况下,您应该遵循这些框架使用的说明和机制。

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

    【讨论】:

    • 我不知道正确的位置,因为我也不知道它是哪个 ViewModel。 LongListSelector 在 MainPage 上,但它显示组模型列表,我希望组内的项目数作为 LongListSelector 的第二行。那么它是 MainViewModel 还是 GroupViewModel 的集合,我应该何时、在哪里存储 GroupViewModel 的集合?
    猜你喜欢
    • 2013-08-04
    • 2014-05-14
    • 2016-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多