在WPF CAL MVVM中初始化模型和视图的正确方法是什么

时间:2010-01-15 15:32:16

标签: wpf mvvm unity-container viewmodel prism

我有两种方法在WPF CAL MVVM中初始化Views和ViewModel。

1 - 似乎更受欢迎。需要您解析ViewModel以自动解析View。 ViewModel包含有关视图的信息。

    public interface IView
    {
        void SetModel(IViewModel model);
    }

    public interface IViewModel
    {
        IView View { get; }
    }

    public class View
    {
        public void SetModel(IViewModel model)
        {
            this.DataContext = model;
        }
    }

    public class ViewModel
    {
        private IView view;

        public ViewModel(IView view)
        {
            this.view = view;
        }

        public IView View { return this.view; }
    }

2 - 似乎更清洁,并从ViewModel中删除了View。需要您解析视图以自动解析ViewModel。将对象注入视图(不确定这是否合适)。

    public interface IView
    {
    }

    public interface IViewModel
    {
    }

    public class View
    {
        private IViewModel model;

        public View(IUnityContainer unityContainer)
        {
            this.model = unityContainer.Resolve<IViewModel>();
            this.DataContext = this.model;
        }
    }

    public class ViewModel
    {
    }

初始化视图和模型的可接受方法是什么,以及每种方法的优缺点是什么。你应该在视图中注入对象吗?

4 个答案:

答案 0 :(得分:3)

它们都是有效的,但#1往往更容易测试(它至少使你的测试更简洁)。 #2的优势在于它更趋于明确,并使维护更加清晰,特别是当你有大量的营业额时,这种事情。少解释(虽然这不是采用它的理由,但这只是一个老生常谈)。

区别在于#1称为依赖注入#2称为服务位置。它们经常被混淆,因为它们通常都使用某种IoC容器(尽管不一定如此)。

最后这是一个偏好的问题,但正如我所说,我认为你会发现#1更容易测试......你不必在测试/模拟中涉及IUnityContainer接口。

答案 1 :(得分:2)

我更喜欢在XAML中定义视图模型,并为类型化访问提供只读属性:

<UserControl ...>
    <UserControl.DataContext>
        <local:MyViewModel/>
    </UserControl.DataContext>

    ...

</UserControl>

public partial class MyView : UserControl, IMyView
{
    public MyViewModel ViewModel
    {
        get { return this.DataContext as MyViewModel; }
    }

    ...
}

答案 2 :(得分:1)

选项1看起来正确,为视图提供对viewmodel的引用。

让视图模型的引用回到视图对我来说似乎有点可疑。这看起来更像是模型 - 视图 - 演示者类型的体系结构。如果您的视图模型与视图交互较重且需要对视图的引用,那么最好将视图模型拆分为纯粹用于数据绑定的视图模型和执行更复杂交互的演示者。

选项2看起来并不正确。将对ioc容器的引用传递给类是我书中的一大代码味道。应尽量减少对IoC容器的调用。在我的大多数应用程序中,我只在程序开始时调用容器来连接东西。通常使用工厂类来完成更多动态对象创建。

答案 3 :(得分:1)

此代码的问题在于选项2烘焙的次数超出了需要。它确实不需要也​​不应该引用容器。

另一种选择允许选项2与选项1一样可测试,但概念上更清晰,因为ViewModel从不知道视图。

如果您想使用xml文件指定布局而不是使用棱镜区域,这将非常有用,这使您可以轻松配置布局。

替代:

public interface IView
{
}

public interface IViewModel
{
}

public class View : IView
{
    private IViewModel model;

    public View(IViewModel m)
    {
        this.model = m;
        this.DataContext = this.model;
    }
}

public class ViewModel : IViewModel
{
}

以及你拥有的其他地方:

Container.RegisterType<IViewModel, ViewModel>( /* appropriate container config */ );
Container.RegisterType<IView, View>(/* appropriate container config */ );

您可以使用以下任意位置创建视图:

Container.Resolve<IViewModel>();