XAF之Frame和Controller

                   在XAF开发中,常常要用到一个方法Frame.GetController<ControllerType>(),该方法的作用是从Frame.Controllers集合中获取某个Controller,但通常我们可能并不只是为了得到该Controller后,而是去访问它拥有的Action或者使用其类包含的方法。大部分时候,直接从Controller中使用该方法都能正常工作,但并不是全部时候。比如在一个DetailView的Controller中,调用Frame.GetController<ControllerType>()方法获取某个ListViewController的Action,并执行该Action.DoExecute()方法时就会出错,运行时会报告该Action并未激活,原因是"Controller active",这实际上就是该ListViewController未激活造成的。所以,问题来了,怎样理解Frame和Controller的关系呢?怎样正确地使用Frame.GetController<ControllerType>()方法?

我在之前一篇博客

XAF之Window, Frame和Template

中已经讲到过Frame和Template的关系。在XAF的每种视图中,都包含了Frame和Template,它们构成了视图的全部定义,而完成的功能则留给了Frame.Controllers中包含的各种Controller。当创建Frame时,它会加载XAF中所有合适的Controller到Frame.Controllers集合中,即为这些Controller调用各自的构造函数创建了新实例,然后就过滤掉不符合条件的Controller,过滤条件有很多,比如我们在VS中设计Controller时的,TargetViewId,TargetViewType, TargetViewNesting, TargetObjectType等等。过滤完成后的Controller就是当前Frame可用的Controller,自然也就可用Frame.GetController<ControllerType>()获取该Controller并可靠访问其成员。而且,也只有通过了过滤的Controller,XAF才会去触发其Actived等等后续事件,注意,FrameAssigned事件是在过滤时触发的,所以要考虑到FrameAssigned中的代码是否会做多余的事情。

              下面以一个简单例子,讲述Frame创建到显示的整个过程:为XAF添加一个DockPanel,在DockPanel中显示当前ListView选中的的Human的地址详情。如图1所示:


图1

代码如下:

private void CreatePanelAction_Execute(object sender, SimpleActionExecuteEventArgs e)
        {
            ListView listView = View as ListView;
            Human man = listView.CurrentObject as Human;

            //要访问XAF中的控件,就需要使用Template
            //Template保存了视图的控件实际信息
            MainForm form = (Application.MainWindow.Template as MainForm);
            //MainForm form = (Frame.Template as MainForm);
            DockManager dockManager = form.DockManager;
            DockPanel panel = dockManager.AddPanel(DockingStyle.Bottom);

            /*
             * Frame类似于一个风筝的骨架
             * 向该骨架中填入Template及View就类似于给风筝糊上纸浆
             * 当CreateFrame创建Frame后,也同时为该Frame新创建了(说明调用了Controller构造函数)
             * 全部的Controller,只不过只有部分被激活(Active)了,实际上,创建Frame的Controller
             * 时还触发了Controller的FrameAssigned事件
             */
            Frame cFrame = Application.CreateFrame(TemplateContext.NestedFrame);
            cFrame.CreateTemplate();
            IObjectSpace objectSpace = Application.CreateObjectSpace();
            DetailView view = Application.CreateDetailView(objectSpace, "Address_DetailView", false, objectSpace.GetObject(man.Address1));
            /*为Frame附加View后,继续过滤Controller
            *将不符合条件的Controller禁用(Deactive)掉
             *不要将这里的激活和禁用和Controller的Actived事件相混淆,
             *整个Controller过滤的过程都没有执行到Actived事件
             */
            cFrame.SetView(view);
            
            panel.ControlContainer.Controls.Clear();
            //这里也印证了Template is Control
            System.Windows.Forms.Control address = cFrame.Template as System.Windows.Forms.Control;
            address.Dock = System.Windows.Forms.DockStyle.Fill;
            panel.Controls.Add(address);
        }


了解了Frame对Controller的新建和过滤的过程,那么也就能理解和使用Frame.GetController方法了。比如,我们现在在一个弹出的DetailView中,点击某个Action做了某些事情后,需要更新主界面状态栏的某些信息,而这些状态信息需要用到适合于主界面的一个MyStatusController,那么获取该Controller的正确方式为:

MyStatusController status=Application.MainWindow.GetController<MyStatusController>();
而不是在DetailView的某个Controller中直接使用:

MyStatusController status=Frame.GetController<MyStatusController>();   //错误



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值