(WPF)DevExpress mvvm+温莎城堡.如何构建POCO视图模型

本文关键字:构建 视图 模型 何构建 POCO 城堡 DevExpress WPF mvvm+ | 更新日期: 2023-09-27 18:27:03

在DevExpress MVVM框架中,您可以定义从ViewModelBase继承的两个标准ViewModels。或者,您可以定义更好、更复杂的POCO视图模型(请参阅此链接)。

建造这样一个";POCO";视图模型,则必须使用ViewModelSourceutil。这将使一个标准的伪类成为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");

现在,使用温莎城堡,我注册了这个:

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视图模型,并允许它们由Castle Windsor注入?

非常感谢。

(WPF)DevExpress mvvm+温莎城堡.如何构建POCO视图模型

我找到了一个解决方案:

创建这个助手类

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());
        }
    }
}

现在,在您的构造函数中,依赖关系将得到解析。

public partial class MainWindow : Window, Interfaces.IMainWindow
{ 
    public MainWindow()
    {
        InitializeComponent();
    }
    public MainWindow(Interfaces.IMainWindowViewModel context)
    {
        InitializeComponent();
        this.DataContext = context;
    }
}