(WPF)DevExpress mvvm + Castle Windsor。如何构建POCO视图模型?

时间:2015-12-17 01:22:06

标签: c# wpf mvvm devexpress castle-windsor

在DevExpress MVVM框架中,您可以定义两个标准ViewModel,继承自ViewModelBase。或者,您可以定义更好,更复杂的POCO ViewModels(see this link)。

要构建此类“POCO”视图模型,必须使用 ViewModelSource util。这将使标准虚拟类成为POCO ViewModel。

namespace DataAbstractWPF.ViewModels
{
    [POCOViewModel]
    public class EntityKindViewModel : Interfaces.ICreateEntityKindViewModel
    {
    }
}

然后,在XAML中,要实例化或定义这样的POCO视图模型,您必须:

         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm" 
         xmlns:ViewModels="clr-namespace:DataAbstractWPF.ViewModels"
         d:DataContext="{dxmvvm:ViewModelSource ViewModels:CreateEntityWizardViewModel}"

如果您将ViewModel动态或简单地传递给View

         xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm" 
         xmlns:ViewModels="clr-namespace:DataAbstractWPF.ViewModels"
         DataContext="{dxmvvm:ViewModelSource ViewModels:CreateEntityWizardViewModel}"

如果您希望ViewModel直接由XAML实例化。

您也可以通过代码

创建它
ViewModelSource.Create<LoginViewModel>();

或者可以由框架创建的工厂。

var factory = ViewModelSource.Factory((string caption) => new LoginViewModel(caption));
factory("Login");

现在,使用Castle Windsor,我注册了这个:

container.Register(Component.For<Interfaces.ICreateEntityKindViewModel>().ImplementedBy<ViewModels.EntityKindViewModel>().LifestyleTransient());
container.Register(Component.For<Interfaces.ICreateEntityWizardViewModel>().ImplementedBy<ViewModels.CreateEntityWizardViewModel>().LifestyleTransient());
container.Register(Component.For<Interfaces.IMainWindowViewModel>().ImplementedBy<ViewModels.MainWindowViewModel>().LifestyleTransient());

container.Register(Component.For<Interfaces.ICreateEntityWizard>().ImplementedBy<Views.CreateEntityWizard>().LifestyleTransient());
container.Register(Component.For<Interfaces.IMainWindow>().ImplementedBy<Views.MainWindow>().LifestyleTransient());
container.Register(Component.For<Interfaces.ICreateEntityKind>().ImplementedBy<Views.EntityKind>().LifestyleTransient());

container.Register(Component.For<Interfaces.IShell>().ImplementedBy<Shell>().LifestyleTransient());

但是现在,当然, ViewModelSource 被完全绕过,曾经美丽的POCO视图模型现在只是一个无用的虚拟对象。

现在,我的问题是,如何使用ViewModelSource创建POCO viewModel,并允许它们由Castle Windsor注入?

非常感谢。

1 个答案:

答案 0 :(得分:1)

我找到了解决方案:

创建此助手类

  String variableNameId   = rs1.getString("recording_id");

创建组件激活器

using System;
using System.Collections.Generic;

namespace DataAbstractWPF.Helpers
{
    public class AttributeHelper
    {

        public static bool HasAttribute(Type implementation, Type attr)
        {
            object[] arr = implementation.GetCustomAttributes(true);
            List<object> list = new List<object>(arr);
            object attrib = list.Find(delegate (object o) { return ( attr.IsAssignableFrom(o.GetType()) ); });
            return attrib != null;
        }

    }
}

像这样创建一个安装程序

using System;
using Castle.MicroKernel.ComponentActivator;
using DevExpress.Mvvm.DataAnnotations;
using DevExpress.Mvvm.Native;
using DataAbstractWPF.Helpers;

namespace DataAbstractWPF.Activators
{
    class DXViewModelActivator : DefaultComponentActivator
    {
        public DXViewModelActivator(Castle.Core.ComponentModel model, Castle.MicroKernel.IKernelInternal kernel, Castle.MicroKernel.ComponentInstanceDelegate onCreation, Castle.MicroKernel.ComponentInstanceDelegate onDestruction)
            : base(model, kernel, onCreation, onDestruction)
        {
            Model.Implementation = TryGetPOCOType(Model.Implementation);
        }

        Type TryGetPOCOType(Type implementation)
        {
            if (AttributeHelper.HasAttribute(implementation, typeof(POCOViewModelAttribute)))
                implementation = ViewModelSourceHelper.GetProxyType(implementation);

            return implementation;
        }

    }
}

现在在你的构造函数中,依赖关系将被解析。

using Castle.MicroKernel.Registration;
using Castle.MicroKernel.SubSystems.Configuration;
using Castle.Windsor;
using DataAbstractWPF.Helpers;
using DevExpress.Mvvm.DataAnnotations;
using DataAbstractWPF.Activators;

namespace DataAbstractWPF.Bootstrapping
{
    public class Installers : IWindsorInstaller
    {
        public void Install(IWindsorContainer container, IConfigurationStore store)
        {

            container.Register(Classes.FromThisAssembly()
                .Where(type => AttributeHelper.HasAttribute(type, typeof(POCOViewModelAttribute)))
                .Configure(r => r.Activator<DXViewModelActivator>())
                .LifestyleTransient()
                .WithServiceDefaultInterfaces()
                );

            container.Register(Component.For<Interfaces.ICreateEntityWizard>().ImplementedBy<Views.CreateEntityWizard>().LifestyleTransient());
            container.Register(Component.For<Interfaces.IMainWindow>().ImplementedBy<Views.MainWindow>().LifestyleTransient());
            container.Register(Component.For<Interfaces.ICreateEntityKind>().ImplementedBy<Views.CreateEntityKind>().LifestyleTransient());

            container.Register(Component.For<Interfaces.IShell>().ImplementedBy<Shell>().LifestyleTransient());
        }

    }
}