ViewModel 包含另一个 ViewModel 的集合 [英] ViewModel contains collection of another ViewModel

查看:20
本文介绍了ViewModel 包含另一个 ViewModel 的集合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在所有关于 MVVM 的教程中,我读到 View 不应该知道 Model,因此引入了 ViewModel 层.

In all tutorial about MVVM I read that View should not know about Model, hence ViewModel layer is introduced.

如果是这样的情况:我们有包含 PackShelf:

If so in situation like: we have Shelf which contains Pack:

namespace Storage.Model
{
    class Pack
    {
        public string Name { get; set; }
    }
}

<小时>

<UserControl x:Class="Storage.View.Shelf" ... >
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="20" />
            <RowDefinition Height="50" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <TextBlock Grid.Row="0" Text="{Binding Path=Name}"/>
        <TextBlock Grid.Row="1" Text="{Binding Path=Capability}"/>
        <ItemsControl Grid.Row="2" ItemsSource="{Binding Path=Packs}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Border>
                        <TextBlock Text="{Binding Name}" /> 
                    </Border>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>

    </Grid>
</UserControl>

<小时>

// DataContext for Shelf 
namespace Storage.ViewModel
{
    public class ShelfViewModel
    {
        public string Name { get; set; }
        public string Capability { get; set; }
        // It's okay that ViewModel contains collection of another ViewModel?
        public ObservableCollection<PackViewModel> Packs { get; set; } 
    }
}

// DataContext for Pack
namespace Storage.ViewModel
{
    class PackViewModel
    {
        private Pack pack;
        public string Name 
        {
           get{ return pack.Name; }
           set{ ... }
        }

        public PackViewModel(int id)
        {
            // How to populate reference to Pack instance?
            pack = (new PackRepository()).getById(id) 
        }
    }
}

就像我在上面的代码注释中提到的那样,一个 ViewModel 创建另一个 ViewModel 的实例可以吗?我可以想象我们有 StorageShelf 集合的情况,因此我们最终得到对 ModelView 的级联引用:StoreViewModel contains ObservableCollection<ShelfViewModel> 包含 ObservableCollection 的集合.

Like I mention in code comment above, it okey that one ViewModel create instances of another ViewModel? I can image case where we have Storage with collection of Shelf, hence we end up with cascading reference to ModelView: StoreViewModel contains ObservableCollection<ShelfViewModel> which cotains collection of ObservableCollection<PackViewModel>.

该解决方案出现的另一个问题是如何根据 Pack 类填充新引入的 PackViewModel?我们必须以某种方式将唯一标识符传递给 PackViewModel 实例.

Another problem with arise with that solution is that how to populate newly introduced PackViewModel with reference to Pack class? We must somehow pass unique identifier to PackViewModel instance.

我不想隐藏这个问题与我的另一个问题有关 应该视图层知道模型类(实体)吗?

I don't want hide that this question is related to my other question Shoud view layer know about model classes (entities)?

推荐答案

就像我在上面的代码注释中提到的那样,一个 ViewModel 创建另一个 ViewModel 的实例可以吗?

Like I mention in code comment above, it okey that one ViewModel create instances of another ViewModel?

是的.在这种情况下,PackViewModel 只是 Pack 的包装器.例如,当您不想直接公开或绑定到模型类型或模型类型未实现 INotifyPropertyChanged 接口时,通常会使用此类包装器.

Yes. In this case PackViewModel is just a wrapper around Pack. You typically use such a wrapper when you don't want to expose or bind to the model type directly or when the model type doesn't implement the INotifyPropertyChanged interface for example.

这完全没问题.你确实会得到更多的类,但每个类都有自己的责任.例如,您可以使用特定于 UI 的属性扩展包装类,即视图绑定到的属性.

This is perfectly fine. You will indeed end up with more classes, but each class has its own responsibility. You could for example extend the wrapper class with properties that are specific to the UI, i.e. properties that are obly there for the view to bind to.

该解决方案出现的另一个问题是如何根据 Pack 类填充新引入的 PackViewModel?我们必须以某种方式将唯一标识符传递给 PackViewModel 实例

Another problem with arise with that solution is that how to populate newly introduced PackViewModel with reference to Pack class? We must somehow pass unique identifier to PackViewModel instance

您可以在创建包装对象时将其注入包装类:

You could just inject the wrapper class with the wrapped object when you create it:

class PackViewModel
{
    private readonly Pack _pack;
    public PackViewModel(Pack pack)
    {
        _pack = pack;
    }

    public string Name
    {
        get { return _pack.Name; }
    }
}

给定您可能从某种存储库或服务收到的 Pack 对象集合,您可以轻松创建包装器对象,例如:

Given a collection of Pack objects that you may have received from some kind of repository or service, you could then easily create wrapper objects, e.g.:

var repo = PackRepository();
var packs = repo.GetPacks();
var wrapperObjects = packs.Select(pack => new PackViewModel(pack));

这篇关于ViewModel 包含另一个 ViewModel 的集合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆