在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注入?
非常感谢。
我找到了一个解决方案:
创建这个助手类
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;
}
}