绿豆.Net

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 :: 管理 ::

Composite UI Application Block 学习笔记之Commands (转)

  听了曹严明先生的《组合型智能客户端应用 With Composite Application Block》的讲座后,对CAB有了一个初步的理解,同时感觉CAB将大有用武之地。于是,本人从微软网站http://practices.gotdotnet.com/projects/cab下载了源代码,开始研究。

    这个学习笔记将主要讲述CAB中Commands的应用,以及一些本人的疑惑,期望园子里的朋友予以指点。

一、何谓Commands.

    Commands是CAB程序集里一个重要的对象,它主要用来关联控件、WorkSpace和业务逻辑,也就是让一个命令可以被多个控件的事件引发。

一般的情况下可以通过以下代码关联一个命令和控件的事件:

    Commands[strCommandName].AddInvoker(objControl, strEventName);

二、建立测试Commands的程序

1.打开VS2005,新建Windows Application项目。

2.添加以下引用

  • Microsoft.Practices.CompositeUI;
  • Microsoft.Practices.CompositeUI.WinForms;
  • Microsoft.Practices.ObjectBuilder

3.此时VS将自动产生program.cs,Form1.cs。将Form1.cs命名为TestForm。

4.给TestForm加入菜单。命名为menuStrip1。依次加入菜单子项,名称如下:

  • AddNew
  • SaveFileTool
  • DeleteFile

5.重命名program.cs为CommandsApplication.cs,并且将内容修改成以下形式:

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using Microsoft.Practices.CompositeUI;
using Microsoft.Practices.CompositeUI.Commands;
using Microsoft.Practices.CompositeUI.WinForms;
using Microsoft.Practices.CompositeUI.UIElements;
class CommandsApplication : FormShellApplication<MainWorkItem, TestForm>
{
/// <summary>
/// The main entry point for the application.
/// </summary>

[STAThread]
public static void Main()
{
  
new CommandsApplication().Run();
}

}


 

修改时要注意将static class 修改成 class,否则无法通过编译,提示类似错误1所示的错误信息

Static class 'TestUIBlock.CommandsApplication' cannot derive from type 'Microsoft.Practices.CompositeUI.WinForms.
FormShellApplication<TestUIBlock.MainWorkItem,TestUIBlock.TestForm>'.
Static classes must derive from object.CommandsApplication.cs 13 40 TestUIBlock。

   如果将static class 修改成 public class,也会无法通过编译,提示类似错误2的信息:

Inconsistent accessibility: base class 'Microsoft.Practices.CompositeUI.WinForms.
FormShellApplication<TestUIBlock.MainWorkItem,TestUIBlock.TestForm>'
is less accessible than class 'TestUIBlock.CommandsApplication' E:\WorkSpace\Projects\TestUIBlock\TestUIBlock\TestUIBlock\CommandsApplication.cs 13 18 TestUIBlock。

    错误1很好理解,就是静态的类无法从类型继承,但是错误2就让我有些费解,在CAB的Quick Start中就是这样写的。和我新建立的不同区别是,我是通过引用dll来添加引用的,Quick Start是直接引用解决方案中的项目。查阅MSDN帮助对Inconsistent accessibility的解释,好像也不能解释我遇到的这个问题。

还有就是要将static void Main()修改成 public static void Main(),同时删除VS2005默认生成的代码。

6.建立Controller,也就是命令。通常业务行为都放到这个类里。

     新建类MainControler文件,将类MainControler从Controller继承。

     编写过程,并且以属性[CommandHandler(strKey)]进行修饰,其中strKey是Commands集合中注册的命令关键字。示例过程写法如下:


 

[CommandHandler("AddNew")]
public void AddNewFileHandler(object sender, EventArgs e)
{
  MessageBox.Show(
"You Had Added A File");
}


 

7.建立WorkItem。

    新建类MainWorkItem,并且从WorkItem继承。

   重载Run()方法,代码如下所示:


 

using System;
using System.Windows.Forms;
using System.Collections.Generic;
using Microsoft.Practices.CompositeUI;
using Microsoft.Practices.CompositeUI.UIElements;
using Microsoft.Practices.CompositeUI.WinForms;
using Microsoft.Practices.ObjectBuilder;
using System.Text;

namespace TestUIBlock
{
 
class MainWorkItem:WorkItem
 
{
  
public override void Run()
  
{
    Items.AddNew
<MainControler>();
    Activate();}

  }

 }

}

 

    在Quick Start中是将通过XML文件,将菜单项记录下来,和Commands集合映射,然后动态加载到主菜单上的。由于我们已经在TestForm中创建了菜单项,所以可以去掉动态加载到主菜单的操作,但是和Commands集合映射是必不可少的。可是在MainWorkItem中我不知道如何访问TestForm实例,去获取每一个菜单项(哪位大哥知道的话,请告诉我),于是我只好将映射到Commands部分的代码放到CommandsApplication中。

    8.建立菜单项到Commands的映射。

    建立方法ProcessCommandMap(IUIElementService uiService):


 

private void ProcessCommandMap(IUIElementService uiService)
{

foreach (ToolStripMenuItem item in ((ToolStripMenuItem)Shell.MainMenuStrip.Items["FileMenue"]).DropDownItems)
{
  
this.RootWorkItem.Commands[item.Name].AddInvoker(item, "Click");
}


     这里是通过菜单项的名称和命令的名称进行映射的。我们也可以将多个控件的事件映射到同一个命令如:

Button btn1 = new Button();
btn1.Text 
= "test";
btn1.Name 
= "btn1";

Panel panel1 
= (Panel)Shell.Controls["panel1"];
panel1.Controls.Add(btn1);
this.RootWorkItem.Commands["AddNew"].AddInvoker(btn1, "Click");

     不知道看过Commands QuikStart的朋友发现没有,通过Service的RegisterUIExtensionSite方法注册菜单的根后,就可以直接通过Service的Add方法将子菜单添加到父菜单。如以下代码:

IUIElementService uiService = RootWorkItem.Services.Get<IUIElementService>();
ToolStripMenuItem fileItem 
= (ToolStripMenuItem)Shell.MainMenuStrip.Items["File"];
uiService.RegisterUIExtensionSite(
"File", fileItem.DropDownItems);

 

    我曾经尝试通过同样的方法在一个Panel中加入一个Button,但是失败了,原因是没有注册对应的UIElementManagerFactory。

9.至此我们已经做好了一个Commands的例子,可以通过F5运行程序了。

 

三、程序的执行顺序

通过调试程序我们不难发现程序是按照以下顺序执行的:

1.通过入口程序CommandsApplication调用 new CommandsApplication().Run();
2.初始化TestForm
3.创建Shell后建立控件和命令的映射,执行AfterShellCreated方法。
4.运行MainWorkItem,激活主窗体。
文中完整代码下载:/Files/hyphappy/TestUIBlock.rar

posted on 2005-11-15 00:09 hyphapy 阅读(2658) 评论(10)  编辑 收藏 引用 网摘 所属分类: C#

View Comments

# re: Composite UI Application Block 学习笔记之Commands  回复  更多评论   
为什么不讲mvp,不讲host,不讲workitem,不讲controller, 不讲SmartPart,不讲DI,而从Command说起? 一来command不是最重要,二来也不是学习cab第一要学的,实在奇怪。
2005-11-15 08:59 | idior.
# re: Composite UI Application Block 学习笔记之Commands  回复  更多评论   
这个东西好像挺新的吧,我就在国外网站上看过,idior讲的MVP,HOST,workitem啥的,都没听过,呵呵。
2005-11-15 09:17 | 蛙蛙池塘
# re: Composite UI Application Block 学习笔记之Commands  回复  更多评论   
to:idior本人也是刚刚接触这个东西,正在研究中。逐渐的会把CAB中的其他概念和应用写出来。
2005-11-15 09:30 | hyphappy
# re: Composite UI Application Block 学习笔记之Commands  回复  更多评论   
建议你从mvp谈起介绍一下它是如何松耦合实现m-v-p三者之间关联的.其中用componetmodel名空间的类库实现了Ioc(DI)(七月份的版本是这样的,现在11月的我还没看). 还有它的那个事件注册机制也是很值得介绍.

另外估计大家学习CAB,最头疼的就是workitem和controller的关系了.如果你能说明一下,再好不过.

2005-11-15 09:45 | idior.
# re: Composite UI Application Block 学习笔记之Commands  回复  更多评论   
期待更深入的内容,谢谢
2005-11-15 17:25 | culturenet
# re: Composite UI Application Block 学习笔记之Commands  回复  更多评论   
听过MVC模式,没有听过MVP模式
2005-11-15 20:16 | upto
# re: Composite UI Application Block 学习笔记之Commands  回复  更多评论   
请问怎么和你联系
2006-06-07 17:28 | zerokai
# re: Composite UI Application Block 学习笔记之Commands  回复  更多评论   
在Quick Start中是将通过XML文件,将菜单项记录下来,和Commands集合映射,然后动态加载到主菜单上的。由于我们已经在TestForm中创建了菜单项,所以可以去掉动态加载到主菜单的操作,但是和Commands集合映射是必不可少的。可是在MainWorkItem中我不知道如何访问TestForm实例,去获取每一个菜单项(哪位大哥知道的话,请告诉我),于是我只好将映射到Commands部分的代码放到CommandsApplication中。



你设置一下mainform 的MainMenuStrip属性,就可以直接引用Shell.MainMenuStrip.Items了,不用建立映射。
2006-09-13 14:30 | prolead
# re: Composite UI Application Block 学习笔记之Commands  回复  更多评论   
请问怎样在菜单中加 这样的快捷键: &Exit

在Xml 里不行,既使行了,运行时也通不过....

如果这样, UI Block 前景...
2007-03-16 20:45 | Jinwmmail@126.com
# re: Composite UI Application Block 学习笔记之Commands  回复  更多评论   
<add id="2" site="MainMenu" label="&amp;Help" register="true" registrationsite="Help" />
posted on 2007-05-17 14:43  杜军  阅读(563)  评论(0)    收藏  举报