CAB(Composite UI Application Block)学习记录

 CAB(Composite UI Application Block)学习记录

CAB话说和MVC及MVP差不多但本人看了三天仍然是一头雾水!

下面把相关资料放上,以共同学习,提前声明如果有侵权请通知我立刻删除!谢谢!

 

 

RootWorkItem.UIExtensionSites.RegisterSite
这个方法设计有什么用?
 
主要是为了便于子模块插入和更新一些菜单,工具按钮之类的东西
 
Site 即是菜单,工具按钮之类的场所,你可以注册多个 site, MainMenu, 标准工具条 Standard, 状态条 StatusBar ,例子
 
RootWorkItem.UIExtendsionSites.RegisterSite("MainMenu",Shell.MainMenuStrip);
RootWorkItem.UIExtendsionSites.RegisterSite("Standard",Shell.ToolBar);
RootWorkItem.UIExtendsionSites.RegisterSite("StatusBar",Shell.StatusBar);
 
默认的,在 form 中的控件都是私有的。 ToolBar,StautsBar 均需要改变 private, public(internal) (需要测试 )
 
MainMenuStrip 显然是 .net 2.0 设置的快捷访问方式,如同 .net 1.1 中的 Menu, 如果你在 form 上放置了一个 MenuStrip mainMenuStrip 属性就反映了这个 MenuStrip
 
一旦注册了 site, 你可以在任意 workitem 中添加自定义的菜单或工具按钮,并进行映射
 
 
在我惯用的写法中, toolbar,menubar 往往为所有模块所共用,当点击一个 save 按钮或菜单时,不同模块的执行动作是不同的,在我早先的插件架构中, IWindowPlugin 有个 AfterComamndClick 方法,传入点击的 command name, 不同模块实现各自的执行方法
 
cab command 显然是另一条路,首先,你编写该模块的各种方法,如 save,delete,refresh 之类的,然后用 CommandHandler 标记为 command, 最后进行映射
 
映射实际上就是,某一菜单或工具按钮该执哪个 workitem 的那个 command 代码
 
 
  如果要一个容器成为一个 UIExtensionSite ,其则要为其实现 IUIElementAdapter 接口,并实现 IUIElementAdapterFactory ,目前, cab 仅支持 ToolStrip,ToolStripItem 及其实现类,这就意味这,像 StatusStrip,MenuStrip,ToolStrip 等均可以注册到 UIExtendSite 集合中,而像 Panel 之类的,显然不行,不过实现起来倒也不是很难, CompositeUI.WinForms.UIElements 一个好的参考
 
由于 IUIElementAdapter 只提供 add,remove 方法,包括 UIExtensionSite 也是,缺少从已存在 site 中取出对象的功能,如果要操作层次型菜单,目前应该是个不太可能的任务,如在主菜单的 file 菜单中增加 filenew 菜单,折衷的办法是将 file 注册为 UIExtensionSite
 
 
在我设想的应用程序类型中,各个子窗口,一般的,像用 tab 表示的共享一个菜单和工具条,但 cab command 显然不适合这种模式。因为在这种模式下,通常有个当前文档的概念,菜单和工具条仅对当前文档有效。在 cab command 模式中,所有注册了 CommandHandler 的过程均会响应,显然,这不是我们希望的。当然,如果像一个保存全部,这样 ,command 还是很有用的

 

cab 快速上手 ( 可能有理解偏差,修改中,欢迎指正 )
cab 显然有太多的概念了,就像我这样的老手 :) ,也难在一天内把握其思路,让我们看看有没有快速使用它的捷径。
第一步
创建一个从 FormShellApplication 继承的类
创建一个 Root Workitem
 
 
  public class CABDemoApplication : FormShellApplication<CABDemoWorkItem,Form1>
    {
  [STAThread()]
        public static void Main()
        {
            CABDemoApplication app = new CABDemoApplication();
            app.Run();
        }
       
    }
 public class CABDemoWorkItem : WorkItem
    {
        }
 
就像这样
第二步
先扔掉 mvc 的概念,改变一下习惯,在以前,我们要创建一个入库输入界面,首先是创建一个 form ,现在,我们是创建一个 user control ,并用 SmartPart attribute 标记这个控件。
  [SmartPart]
    public partial class InStockInput : UserControl
    {
        public InStockInput()
        {
            InitializeComponent();
        }
    }
在这个控件中实现所有逻辑
 
第三步
最后就是显示这个 control ,这个任务的代码都是类似的
首先,我们需要将这个 control 加入到 workitem SmartPart 集合
其次,我们在一个指定的 workspaces 中显示它
请大家注意加粗的两行代码,通常,我们选择在 OnRunStarted 中将视图加入到集合中
但是,显示的通常不一定是在这个过程中,它可以在点击菜单或是点击某个特定的树状导航节点时进行
 
public class CABDemoWorkItem : WorkItem
    {
        protected override void OnRunStarted()
        {
            base.OnRunStarted();
             InStockQueryView csp = this.SmartParts.AddNew<InStockQueryView>();
            Workspaces["InStockQueryWorkspace"].Show(csp);
        }
    }
 
第四步 - 概念进阶
SmartPart SmartPartInfo
这点其实很好理解,就是 smartpart 和描述分离,我的插件框架中就有 plugin plugindescriptor,smartpart smartpartinfo 也是一个理
TabSmartPartInfo 就提供了这个 smartpart 显示在 tabworkspace 中的一些 descriptor, tab 上的文本是什么,显示的时侯是否设置这个 smartpart 为活动的,显示在最后还是最前等。
一个 smartpart 可以有多个 smartpartinfo, 这样,当其显示在不同的 workspace 中,可以呈现不同的外观 , 待验证
 
mvc
model-view-controller
这里 model 是数据,他可以是一个 dataset,datatable 或是一个 entity 类,如 Customer,Area,model view,controller 共用(即这两者均会用到 )
view- 在这里 ,view 特指标注上 SmartPart attribute usercontrol view controller 请求数据并显示数据,标准的 mvc 设计中, view 总是需要依赖一个或多个 controller
为了减少这个依赖,为 controller 抽象一个接口是一个好的想法,让 view 依赖 controller 的接口而不是具体的 controller 类,当然,这在 quick and dirty 的设计环境中,并不需要这样。
controller — 这里, controller 是指继承 Controller 类的一个普通的 .net 对象,它从 view 中获得参数,处理后返回数据给 view
 
mvc  services
严格的设计中, controller 不处理业务逻辑,业务逻辑将转发到 services 层去进行,这里为了减少 controller services 的依赖,通常也为 services 抽象接口
 
WorkItem MVC
WorkItem mvc 之上,它是一个 module 的启动点,如 InStockWorkItem.Run, workitem 中,通常的任务就是作初始化和显示 view
一个 workitem ,按文档中说是一个 usecase ,显然它是从宏观上来看应用程序布局,在 mvc 中, controller,view 等都在做更细致的工作
Module
小的项目,可以将所有实现在一个项目中完成,必要时可以使用文件夹和命名空间进行分离。 cab  本质上是一个插件应用程序。各人可以做自己的项目,然后再合并,为了让 cab 定位这些项目 ,cab 中引入了 module 的概念
一个 Module 是一个 class library 或是 user control 项目
assemblyinfo.cs 中有一下 attribue 标识
[assembly: Microsoft.Practices.CompositeUI.Module("mainMod")]
mainMod 是模块名,在设置模块依赖时有用
一个 module 可能依赖其它模块,这时需要使用 ModuleDependency attribute
[assembly: Microsoft.Practices.CompositeUI.ModuleDependency(
                                         "TheModuleYouDependOn")]
模块初始化
·                         创建一个从 ModuleInit 继承的类
·                         如果需要程序化加载服务 , 覆盖 AddService 方法
·                         如果需要显示用户接口或是定制逻辑,覆盖 Load 方法
最后一步,就是便是 ProfileCatalog.xml ,这个文件同 app.config 在同一个位置,使应用 load 这些模块
<?xml version="1.0" encoding="utf-8" ?>
<SolutionProfile xmlns="http://schemas.microsoft.com/pag/cab-profile">
 <Modules>
    <ModuleInfo AssemblyFile="Mod1.dll"/>
    <ModuleInfo AssemblyFile="Mod2.dll"/>
 </Modules>
</SolutionProfile>
过度设计
通常,你需要明确以上的思路,这是你重构应用的准则,但在实际中,你并不需要像这样做,我个人而言,是否做严格的分离完全取决于你是否能够掌控代码,如果代码的规模在你能把握的范围内,全部的东西都在 view 端也是可以的,怎么顺手怎么来
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值