11. 【DevExpress MVVM】ViewModel的管理

本文描述了如何在运行时取出ViewModel实例。注意,如果在设计时使用MvvmContext组件来构建MVVM化的应用程序,该组件将自动管理视图模型。

如果ViewModel遵循POCO原则,那么MVVM框架会动态地将这个ViewModel转换为包含必要基础设施(例如,支持简化的数据绑定)的新类。框架使用动态创建的类实例,这意味着您不能在运行时初始化访问这些实例,因为它们的类型还没有确定。

请使用下面的选项来取出运行时的ViewModel:

  1. ViewModelSource.Create 方法

    在这种方法中,您首先创建一个ViewModel实例,然后调用SetViewModel方法将该实例与特定的ViewModel类型关联起来。
    var mainViewModel = ViewModelSource.Create<MainViewModel>();
    mvvmContext1.SetViewModel(typeof(MainViewModel), mainViewModel);
  2. ViewModelBase类

    您可以创建一个ViewModel,它须继承自实现了MVVM框架特性的ViewModelBase类。在这种情况下,您可以直接创建ViewModel实例。但请注意,您还需要调用SetViewModel方法来指定框架在需要ViewModel时应该使用这个实例。
     
    public class ViewModel : ViewModelBase {
        //. . .
    }
    var myViewModel = new ViewModel();
    mvvmContext1.SetViewModel(typeof(ViewModel), myViewModel);
    我们不建议使用这种方法,因为这样会丢失POCO模型所提供的所有特性。
  3. ViewModelCreate事件

    这种方法被设计用于依赖注入框架(如Ninject)。下面的示例说明了这种注入方式,是如何与Ninject框架一起工作的。
     
    public class SamuraiViewModel {
        public IWeapon Weapon { get; private set; }
        public SamuraiViewModel(IWeapon weapon) {
            this.Weapon = weapon;
        }
        public void Attack() {
            Weapon.Hit();
        }
    }
    
    // 为IWeapon绑定一个依赖
    kernel.Bind<IWeapon>().To<Sword>();
    
    // 装配MVVMContext
    var fluent = mvvmContext1.OfType<SamuraiViewModel>();
    fluent.BindCommand(simpleButton1, x => x.Attack());
    在这个场景中,您需要动态生成视图模型并将它们绑定到接口(当直接将接口绑定到POCO时,MVVM框架特性将丢失)。要获得所需的实例,处理常规(本地)或静态(全局)ViewModelCreate事件如下:
     
    // 使用Ninject内核取出存活的POCO ViewModel实例
    //常规事件
    mvvmContext1.ViewModelCreate += MVVMContext_ViewModelCreate;
    void MVVMContext_ViewModelCreate(object sender, DevExpress.Utils.MVVM.ViewModelCreateEventArgs e) {
        // kernel.Bind<SamuraiViewModel>().To(e.RuntimeViewModelType);
        // e.ViewModel = kernel.Get<SamuraiViewModel>();
        e.ViewModel = kernel.Get(e.RuntimeViewModelType);
    }
    //静态事件
    MVVMContextCompositionRoot.ViewModelCreate += (s,e)=> {
        e.ViewModel = kernel.Get(e.RuntimeViewModelType);
    };
    静态ViewModelCreate事件是一个弱事件。如果它包含一个对一个变量(上面示例中的“kernel”或下面Autofac示例中的“rootContainer”作用域)的闭包,其生存期比父容器的生存期短,则VS垃圾收集器可以提前收集这个变量,并且事件处理程序可能永远不会被调用。
     
    [STAThread]
    static void Main() {
        //rootContainer被声明在Main方法级上
        IContainer rootContainer;
        var builder = new ContainerBuilder();
        builder.RegisterType<TestViewModel>();
        builder.RegisterType<MyClass>().As<IService>();
        rootContainer = builder.Build();
        MVVMContextCompositionRoot.ViewModelCreate += (s, e) => {
            using (var scope = rootContainer.BeginLifetimeScope(
                b => b.RegisterType(e.RuntimeViewModelType).As(e.ViewModelType))) {
                e.ViewModel = scope.Resolve(e.ViewModelType);
            }
        };
    }
    要解决这个潜在问题,可以在执行订阅的对象的级别上,将变量声明为属性/字段。
     
    //rootContainer被声明在root级别上
    private static IContainer rootContainer { get; set; }
    [STAThread]
    static void Main()
    {  
        var builder = new ContainerBuilder();
        builder.RegisterType<TestViewModel>();
        builder.RegisterType<MyClass>().As<IService>();
        rootContainer = builder.Build();
        MVVMContextCompositionRoot.ViewModelCreate += (s, e) =>
        {
            using (var scope = rootContainer.BeginLifetimeScope(
                b => b.RegisterType(e.RuntimeViewModelType).As(e.ViewModelType))) {
                    e.ViewModel = scope.Resolve(e.ViewModelType);
                }
        };
    }

【DevExpress MVVM】中文翻译系列.文章目录

DevExpress.WindowsForms.v20.1.chm离线英文原版文档下载

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值