一、简单概念介绍
CAB提供一个开发环境能很好的隐藏复杂度和提高生产力,通过高度抽象和关注点的分离,开发人员能够关注于业务逻辑提高基础框架代码的复用。Smart Part是整个CAB体系中重要的一部分,它可以将界面独立于业务逻辑,让界面和业务逻辑松散的耦合起来。Smart Part的应用中有几个重要概念:
WorkSpace:作为一个容器,它可以统一的添加和显示视图。CAB中提供了一组控件作为视图的容器,包括DeckWorkSpace,MDIWorkSpace,TabWorkSpace,WindowWorkSpace,ZoneWorkSpace。它们的作用有点类似普通Windows 控件Panel,MDI窗口,TAB控件,Window窗体。在程序中根据名称可以通过WorkItem的WorkSpace集合索引到它们。
Smart Part: 也可以被称作View,实际上是一个个自定义的控件。
其他像WorkItem, State之类的概念我在前两次的学习笔记中曾经介绍过了,这里就不再罗嗦了。
我们利用CAB中WorkSpace和Smart Part到底可以做些什么呢?WorkSpace可以一致的显示多个控件,Shell 开发人员创建定制的 workspaces 以提供控件周围相似的框架和修饰,共享的布局和定位,眩目的界面切换。下面我们还是通过一个实例来逐步理解CAB之Smart Part应用给我们带来的好处,特别是在多个数据来源,将多个界面块组合成一个统一美观的整体时的应用方便性。
二、实例研究
1.应用场景
我相信研究过CAB的朋友肯定知道微软提及的一个应用案例,Dell的客服桌面应用。该应用就是为了提高克服人员的办公效率,将在提供客户服务过程中需要从多个软件系统获取的信息,统一的集成到一个界面上来。也许大家会为该应用卓越的表现力,而感到亲切、人性化,其实类似这样的应用我们通过CAB基础件的应用,也可以达到类似的效果,而不需要在界面化太多的精力去处理业务和界面之间的交互。为了能够说明问题,我在学习过程中也做了一个简单的例子。
大家可能都开发过网站或者用过Share point portal,那大家肯定都应该知道Web Part这个概念,在CAB中类似的有了Smart Part的概念。Web Part能将一个个的信息块集成到一个统一的Portal,Smart Part也能将不同的信息块集成到一个界面。我们不妨假设这样一个应用场景:
假设您是某百货店的店长,希望每天能看到店里的销售业绩,能看到自己每天的邮件,能看到自己喜欢的Blog上的资源,能有软件提示自己每天的行程安排,最重要的是这些信息需要在一个统一的界面上显示出来。面对这样的需求,CAB来开发界面大有用武之地,如果采用SOA的架构,更能使遗产系统的价值利用得更好。
2.需求分析
具体来说该软件有以下需求:
a.销售业绩的信息从店面现有的进销存系统中获得。
b.Blog信息通过RSS获得
c.每天的日程安排情况从秘书给自己设定的OA系统中获得。
d.电子邮件通过集团统一的电子邮件系统中获得,该邮件系统支持Web Service。
e.软件界面简单统一,不能有过多的界面切换,最好能将所有概要信息显示在一个界面之上。
f.软件开发周期要短,尽量利用现有系统的数据和逻辑。
g.界面可能会扩展,以后可能需要集成更多的系统。
面对这些需求,我们不难得出结论:用CAB基础件开发界面,用Web Service集成遗产系统信息都是不错的选择。
3.开始建立应用
由于本例我们主要是为了学习CAB,至于Web Service的应用不做阐述。为了模拟类似的效果,和SOA系统开发过程中共享契约的原则,我们通过数据集来代表契约(XSD文件),用实际的XML文件代表Web Service的返回结果。
第一步:建立解决方案
a.启动VS2005,新建windows application,命名为TestSmartPart在项目中引用以下组件:
- Microsoft.Practices.CompositeUI;
- Microsoft.Practices.CompositeUI.WinForms;
- Microsoft.Practices.ObjectBuilder
第二步:绘制主窗口
a.将系统默认产生的Form1窗体,命名为TestSmartPartForm。
b.通过菜单-->工具-->自定义工具箱,选择浏览Microsoft.Practices.CompositeUI.WinForms.dll,这是工具箱中能出现DeckWorkSpace,MDIWorkSpace等控件。
           c.打开TestSmartPartForm的设计视图,调整窗体的高度和宽度,绘制5个DeckWorkSpace控件,分别命名为deckWS_Calendar,deckWS_Blogs,deckWS_Plan,deckWS_Task,deckWS_MainEmail。最终的界面效果如下图:
      
      
         
      
      
      
    
第三步:定义数据实体(或者定义服务契约)
a.新建DataSources文件夹。
b.在DataSources文件夹中添加myBlogs,myEmail,myTasks,myPlans四个数据集。具体结构在文中不作描述,大家可以参考文后的源代码。
c.根据数据集的结构,建立数据源。这里我们用Xml文件来代替数据库中读取的数据,分别添加myBlogs.xml,myEmail.xml,myTasks.xml,myPlans.xml。数据的内容我在此略过。将各个Xml文件内容录入完成后,拷贝到运行目录。 我不知道为什么设置文件的Copy To OutPut Dierctory属性为always,VS.Net编译项目的时候无法复制到输出目录,难道该属性是在建立安装程序才起作用? 后来我发现是生成的时候连同DataSource文件夹,一起输出到了Bin目录,因此读取的时候也需要加上DataSource目录。
第四步:建立视图
a.建立BlogView、DailyPlan、DailyTask、Emails四个文件夹,这样做的目的只是为了让项目的结构更加清晰,同时以后要是对这些视图进行扩展,也可以把子视图都放到对应的文件夹里。
         b.在项目根目录下添加UserControl,命名为TitlePart.cs。给该用户控件加上一个lable控件,并且加入以下代码:
      
    
 using
      
      
         System;
      
        using
      
      
         System;
         using
      
      
         System.Collections.Generic;
      
      
        using
      
      
         System.Collections.Generic;
         using
      
      
         System.ComponentModel;
      
      
        using
      
      
         System.ComponentModel;
         using
      
      
         System.Drawing;
      
      
        using
      
      
         System.Drawing;
         using
      
      
         System.Data;
      
      
        using
      
      
         System.Data;
         using
      
      
         System.Text;
      
      
        using
      
      
         System.Text;
         using
      
      
         System.Windows.Forms;
      
      
        using
      
      
         System.Windows.Forms;
         using
      
      
         Microsoft.Practices.CompositeUI.SmartParts;
      
      
        using
      
      
         Microsoft.Practices.CompositeUI.SmartParts;
         
         namespace
      
      
         TestSmartPart
      
      
        namespace
      
      
         TestSmartPart
         
         
      
      
         {
      
      
        
          {
           [SmartPart]
          [SmartPart]
           public
        
        
           partial 
        
        
          class
        
        
           TitlePart : UserControl
        
        
          public
        
        
           partial 
        
        
          class
        
        
           TitlePart : UserControl
           
           
        
        
           {
        
        
          
            {
             
             public
          
          
             TitlePart()
          
          
            public
          
          
             TitlePart()
             
             
          
          
             {
          
          
            
              {
               InitializeComponent();
              InitializeComponent();
               }
              }
            
          
          
             
             
             /**/
          
          
            
              ///
            
            
               
            
            
              <summary>
          
          
            /**/
          
          
            
              ///
            
            
               
            
            
              <summary>
            
            
               ///
            
            
               Text that will show in the title label.
            
            
              ///
            
            
               Text that will show in the title label.
               ///
            
            
               
            
            
              </summary>
            
            
              ///
            
            
               
            
            
              </summary>
            
            
            
          
           public
          
          
             
          
          
            string
          
          
             Title
          
            public
          
          
             
          
          
            string
          
          
             Title
             
             
          
          
             {
          
          
            
              {
               get
            
            
              get
            
            
               
               
            
            
               {
            
            
              
                {
                 return
              
              
                 lblTitle.Text;
              
              
                return
              
              
                 lblTitle.Text;
                 }
                }
              
            
            
               set
            
            
              set
            
            
               
               
            
            
               {
            
            
              
                {
                 lblTitle.Text 
              
              
                =
              
              
                 value;
                lblTitle.Text 
              
              
                =
              
              
                 value;
                 }
                }
              
            
            
               }
              }
            
          
          
             
             
             /**/
          
          
            
              ///
            
            
               
            
            
              <summary>
          
          
            /**/
          
          
            
              ///
            
            
               
            
            
              <summary>
            
            
               ///
            
            
               Tooltip for the smartpart.
            
            
              ///
            
            
               Tooltip for the smartpart.
               ///
            
            
               
            
            
              </summary>
            
            
              ///
            
            
               
            
            
              </summary>
            
            
            
          
           public
          
          
             
          
          
            string
          
          
             Description
          
            public
          
          
             
          
          
            string
          
          
             Description
             
             
          
          
             {
          
          
            
              {
               get
            
            
              get
            
            
               
               
            
            
               {
            
            
              
                {
                 return
              
              
                 toolTip.GetToolTip(lblTitle);
              
              
                return
              
              
                 toolTip.GetToolTip(lblTitle);
                 }
                }
              
            
            
               set
            
            
              set
            
            
               
               
            
            
               {
            
            
              
                {
                 toolTip.SetToolTip(lblTitle, value);
                toolTip.SetToolTip(lblTitle, value);
                 }
                }
              
            
            
               }
              }
            
          
          
             }
            }
          
        
        
           }
          }
        
      
    
c.建立BlogView视图。在文件夹BlogView新建UserControl,命名为myBlogView.cs。将该类从TitlePart继承,将标题设置为“我的博客".加入Grid控件和数据集myBlogs进行绑定。最终效果如下图:
d.建立dailyPlanView视图。在文件夹DailyPlan中新建用户控件,命名为myPlan.cs。将该类从TitlePart继承,将标题设置为“我的日程"。加入Grid控件和数据myPlans进行绑定。
e.建立myTaskView视图。在文件夹DailyTask中新建一个UserControl,命名为myTask.cs,将该类从TitlePart继承,将标题设置为“销售报表"。进入myTask.cs的设计时加入控件reportView1,同时根据myTask数据集建立柱状图。最终界面如下图:
f.建立EmailView视图。为了表现WorkSpace能够层层显示子视图,我们在EmailView视图上,添加了两个DeckworkSpace用来显示邮件的列表视图和详细信息视图。EmailView本身又是通过上一级WorkSpace显示的。这里略去邮件列表视图和邮件详细信息视图的建立过程,请参前面视图建立过程和源代码。
到此我们基本上完成各个视图的建立,大家不难发现,他们之间是相对独立的,和WorkSpace无关的。
      
        第五步:编写WorkItem和Controller,连接所有视图
        
      
    
         a.建立应用入口类。新建SmartPartApplication.cs,将类代码修改成以下形式:
      
    
 using
      
      
         System;
      
        using
      
      
         System;
         using
      
      
         System.Collections.Generic;
      
      
        using
      
      
         System.Collections.Generic;
         using
      
      
         System.Windows.Forms;
      
      
        using
      
      
         System.Windows.Forms;
         using
      
      
         Microsoft.Practices.CompositeUI;
      
      
        using
      
      
         Microsoft.Practices.CompositeUI;
         using
      
      
         Microsoft.Practices.CompositeUI.WinForms;
      
      
        using
      
      
         Microsoft.Practices.CompositeUI.WinForms;
         using
      
      
         System.Data;
      
      
        using
      
      
         System.Data;
         
         namespace
      
      
         TestSmartPart
      
      
        namespace
      
      
         TestSmartPart
         
         
      
      
         {
      
      
        
          {
           //
        
        
          注意这句程序,它能将窗体和特定的WorkItem关联。没有没有特定的WorkItem,采用默认的“WorkItem”代替“SmartRootWorkItem”。
        
        
          //
        
        
          注意这句程序,它能将窗体和特定的WorkItem关联。没有没有特定的WorkItem,采用默认的“WorkItem”代替“SmartRootWorkItem”。
        
        
           class
        
        
           SmartPartApplication : FormShellApplication
        
        
          <
        
        
          SmartRootWorkItem, TestSmartPartForm
        
        
          >
        
        
          class
        
        
           SmartPartApplication : FormShellApplication
        
        
          <
        
        
          SmartRootWorkItem, TestSmartPartForm
        
        
          >
        
        
           
           
        
        
           {
        
        
          
            {
             
             /**/
          
          
            
              ///
            
            
               
            
            
              <summary>
          
          
            /**/
          
          
            
              ///
            
            
               
            
            
              <summary>
            
            
               ///
            
            
               The main entry point for the application.
            
            
              ///
            
            
               The main entry point for the application.
               ///
            
            
               
            
            
              </summary>
            
            
              ///
            
            
               
            
            
              </summary>
            
            
            
          
           [STAThread]
          
            [STAThread]
             public
          
          
             
          
          
            static
          
          
             
          
          
            void
          
          
             Main()
          
          
            public
          
          
             
          
          
            static
          
          
             
          
          
            void
          
          
             Main()
             
             
          
          
             {
          
          
            
              {
               new
            
            
               SmartPartApplication().Run();
            
            
              new
            
            
               SmartPartApplication().Run();
               }
              }
            
          
          
             protected
          
          
             
          
          
            override
          
          
             
          
          
            void
          
          
             BeforeShellCreated()
          
          
            protected
          
          
             
          
          
            override
          
          
             
          
          
            void
          
          
             BeforeShellCreated()
             
             
          
          
             {
          
          
            
              {
               base
            
            
              .BeforeShellCreated();
            
            
              base
            
            
              .BeforeShellCreated();
               }
              }
            
          
          
             
          
        
      
    
b.建立根级别的WorkItem。在本例中WorkItem的主要作用是提供显示试图的方法,将业务实体数据填充到数据集,并且让数据集和控件绑定。
以显示BlogView为例,我们来说明WorkItem是如何将BlogView展示到特定的WorkSpace的。首先我们来看以下代码:
 using
      
      
         System;
      
        using
      
      
         System;
         using
      
      
         System.Collections.Generic;
      
      
        using
      
      
         System.Collections.Generic;
         using
      
      
         System.Text;
      
      
        using
      
      
         System.Text;
         using
      
      
         Microsoft.Practices.CompositeUI;
      
      
        using
      
      
         Microsoft.Practices.CompositeUI;
         using
      
      
         Microsoft.Practices.CompositeUI.SmartParts;
      
      
        using
      
      
         Microsoft.Practices.CompositeUI.SmartParts;
         using
      
      
         Microsoft.Practices.ObjectBuilder;
      
      
        using
      
      
         Microsoft.Practices.ObjectBuilder;
         using
      
      
         System.Data;
      
      
        using
      
      
         System.Data;
         
         namespace
      
      
         TestSmartPart
      
      
        namespace
      
      
         TestSmartPart
         
         
      
      
         {
      
      
        
          {
           public
        
        
           
        
        
          class
        
        
           SmartRootWorkItem : WorkItem
        
        
          public
        
        
           
        
        
          class
        
        
           SmartRootWorkItem : WorkItem
           
           
        
        
           {
        
        
          
            {
             
             private
          
          
             TestSmartPart.BlogView.myBlogView blogView;
          
          
            private
          
          
             TestSmartPart.BlogView.myBlogView blogView;
             
             public
          
          
             
          
          
            override
          
          
             
          
          
            void
          
          
             Run()
          
          
            public
          
          
             
          
          
            override
          
          
             
          
          
            void
          
          
             Run()
             
             
          
          
             {
          
          
            
              { 
               ShowBlogView();
              ShowBlogView();
               
               }
              }
            
          
          
             
             
             private
          
          
             
          
          
            void
          
          
             ShowBlogView()
          
          
            private
          
          
             
          
          
            void
          
          
             ShowBlogView()
             
             
          
          
             {
          
          
            
              {
               this
            
            
              .State[
            
            
              "
            
            
              BlogDataSet
            
            
              "
            
            
              ] 
            
            
              =
            
            
               
            
            
              new
            
            
               DataSet();
            
            
              this
            
            
              .State[
            
            
              "
            
            
              BlogDataSet
            
            
              "
            
            
              ] 
            
            
              =
            
            
               
            
            
              new
            
            
               DataSet();
               ((DataSet)
            
            
              this
            
            
              .State[
            
            
              "
            
            
              blogDataSet
            
            
              "
            
            
              ]).ReadXml(
            
            
              "
            
            
              myBlogs.xml
            
            
              "
            
            
              );
              ((DataSet)
            
            
              this
            
            
              .State[
            
            
              "
            
            
              blogDataSet
            
            
              "
            
            
              ]).ReadXml(
            
            
              "
            
            
              myBlogs.xml
            
            
              "
            
            
              );
               
               IWorkspace blogWorkspace 
            
            
              =
            
            
               
            
            
              this
            
            
              .Workspaces[
            
            
              "
            
            
              deckWS_Blogs
            
            
              "
            
            
              ];
              IWorkspace blogWorkspace 
            
            
              =
            
            
               
            
            
              this
            
            
              .Workspaces[
            
            
              "
            
            
              deckWS_Blogs
            
            
              "
            
            
              ];
               blogView 
            
            
              =
            
            
               
            
            
              this
            
            
              .Items.AddNew
            
            
              <
            
            
              TestSmartPart.BlogView.myBlogView
            
            
              >
            
            
              (
            
            
              "
            
            
              BlogView
            
            
              "
            
            
              );
              blogView 
            
            
              =
            
            
               
            
            
              this
            
            
              .Items.AddNew
            
            
              <
            
            
              TestSmartPart.BlogView.myBlogView
            
            
              >
            
            
              (
            
            
              "
            
            
              BlogView
            
            
              "
            
            
              );
               blogWorkspace.Show(blogView);
              blogWorkspace.Show(blogView);
               
               }
              }
            
          
          
             
             }
            }
          
        
        
           }
          }
        
      
    
           系统通过入口程序会自动调用SmartRootWorkItem的Run方法,然后调用ShowBlogView方法来显示Blog视图。我们需要重点关注的是ShowBlogView本身。在显示视图之前我们需要为视图中用到的数据,创建实例并且将其载入WorkItem的State列表,以便在视图和Controller中共享使用。如代码:
      
    
 this
      
      
        .State[
      
      
        "
      
      
        BlogDataSet
      
      
        "
      
      
        ] 
      
      
        =
      
      
         
      
      
        new
      
      
         DataSet();
      
        this
      
      
        .State[
      
      
        "
      
      
        BlogDataSet
      
      
        "
      
      
        ] 
      
      
        =
      
      
         
      
      
        new
      
      
         DataSet();
         ((DataSet)
      
      
        this
      
      
        .State[
      
      
        "
      
      
        blogDataSet
      
      
        "
      
      
        ]).ReadXml(
      
      
        "
      
      
        myBlogs.xml
      
      
        "
      
      
        );
        ((DataSet)
      
      
        this
      
      
        .State[
      
      
        "
      
      
        blogDataSet
      
      
        "
      
      
        ]).ReadXml(
      
      
        "
      
      
        myBlogs.xml
      
      
        "
      
      
        );
      
    
          最后我们需要将视图,在住窗体的deckWS_Blogs控件中显示。在WorkItem中我们直接可以通过this.Workspace[]来索引住窗体上的Workspace,CAB已经自动将在设计时添加的Workspace控件添加到了Workspaces列表。索引导特定的Workspace后,我们需要将要显示的试图添加到WorkItem的Items集合,最后通过Workspace.Show(view)来显示视图。代码如下:
      
          
    
 IWorkspace blogWorkspace 
      
      
        =
      
      
         
      
      
        this
      
      
        .Workspaces[
      
      
        "
      
      
        deckWS_Blogs
      
      
        "
      
      
        ];
      
        IWorkspace blogWorkspace 
      
      
        =
      
      
         
      
      
        this
      
      
        .Workspaces[
      
      
        "
      
      
        deckWS_Blogs
      
      
        "
      
      
        ];
         blogView 
      
      
        =
      
      
         
      
      
        this
      
      
        .Items.AddNew
      
      
        <
      
      
        TestSmartPart.BlogView.myBlogView
      
      
        >
      
      
        (
      
      
        "
      
      
        BlogView
      
      
        "
      
      
        );
        blogView 
      
      
        =
      
      
         
      
      
        this
      
      
        .Items.AddNew
      
      
        <
      
      
        TestSmartPart.BlogView.myBlogView
      
      
        >
      
      
        (
      
      
        "
      
      
        BlogView
      
      
        "
      
      
        );
         blogWorkspace.Show(blogView);
        blogWorkspace.Show(blogView);
      
    
         其他视图的添加方法类似,我就不再做说明。
      
         c.正对根级别的WorkItem,建立对应的Controller。新建RootController.cs,将RootController类从Controller继承,加入以下代码,将其与WorkItem关联。
      
    
 private
      
      
         SmartRootWorkItem rootWorkItem 
      
      
        =
      
      
         
      
      
        null
      
      
        ;
      
        private
      
      
         SmartRootWorkItem rootWorkItem 
      
      
        =
      
      
         
      
      
        null
      
      
        ;
         
         [ServiceDependency(Type 
      
      
        =
      
      
         
      
      
        typeof
      
      
        (WorkItem))]
        [ServiceDependency(Type 
      
      
        =
      
      
         
      
      
        typeof
      
      
        (WorkItem))]
         public
      
      
         SmartRootWorkItem RootWorkItem
      
      
        public
      
      
         SmartRootWorkItem RootWorkItem
         
         
      
      
         {
      
      
        
          {
           set
        
        
          set
        
        
           
           
        
        
           {
        
        
          
            {
             rootWorkItem 
          
          
            =
          
          
             value;
            rootWorkItem 
          
          
            =
          
          
             value;
             }
            }
          
        
        
           }
          }
        
      
    同时为了将业务实体和WorkItem、View结合起来,我们将数据集通过State列表共享。如以下代码:
 [State(
      
      
        "
      
      
        BlogDataSet
      
      
        "
      
      
        )]
      
        [State(
      
      
        "
      
      
        BlogDataSet
      
      
        "
      
      
        )]
         public
      
      
         DataSet BlogDataSet
      
      
        public
      
      
         DataSet BlogDataSet
         
         
      
      
         {
      
      
        
          {
           set
        
        
          set
        
        
           
           
        
        
           {
        
        
          
            {
             if
          
          
             (value 
          
          
            !=
          
          
             
          
          
            null
          
          
             
          
          
            &&
          
          
             State 
          
          
            !=
          
          
             
          
          
            null
          
          
            )
          
          
            if
          
          
             (value 
          
          
            !=
          
          
             
          
          
            null
          
          
             
          
          
            &&
          
          
             State 
          
          
            !=
          
          
             
          
          
            null
          
          
            )
             
             
          
          
             {
          
          
            
              {
               State[
            
            
              "
            
            
              BlogDataSet
            
            
              "
            
            
              ] 
            
            
              =
            
            
               value;
              State[
            
            
              "
            
            
              BlogDataSet
            
            
              "
            
            
              ] 
            
            
              =
            
            
               value;
               }
              }
            
          
          
             }
            }
          
        
        
           get
        
        
          get
        
        
           
           
        
        
           {
        
        
          
            {
             return
          
          
             (DataSet)State[
          
          
            "
          
          
            BlogDataSet
          
          
            "
          
          
            ];
          
          
            return
          
          
             (DataSet)State[
          
          
            "
          
          
            BlogDataSet
          
          
            "
          
          
            ];
             }
            }
          
        
        
           }
          }
        
      
    
         RootController类中当然还共享了其他如DailyPlan、DailyTask等业务数据,由于篇幅不再列出,在源代码中可以查看。
      
    
第六步:修改视图代码,在视图中显示数据。
我们还是以BlogView为例来说明,视图是如何将数据显示出来的,其他视图都相似,请参考源代码。在视图中主要是通过私有变量和加有[State]修饰符的属性和业务数据、Controller相关联的。代码如下:
 private
      
      
         RootController controller 
      
      
        =
      
      
         
      
      
        null
      
      
        ;
      
        private
      
      
         RootController controller 
      
      
        =
      
      
         
      
      
        null
      
      
        ;
         
         [CreateNew]
        [CreateNew]
         public
      
      
         RootController Controller
      
      
        public
      
      
         RootController Controller
         
         
      
      
         {
      
      
        
          {
           set
        
        
          set
        
        
           
           
        
        
           {
        
        
          
            {
             controller 
          
          
            =
          
          
             value;
            controller 
          
          
            =
          
          
             value;
             }
            }
          
        
        
           }
          }
        
      
      
         
         private
      
      
         DataSet blogDataSet 
      
      
        =
      
      
         
      
      
        null
      
      
        ;
      
      
        private
      
      
         DataSet blogDataSet 
      
      
        =
      
      
         
      
      
        null
      
      
        ;
         
         [State]
        [State]
         public
      
      
         DataSet BlogDataSet
      
      
        public
      
      
         DataSet BlogDataSet
         
         
      
      
         {
      
      
        
          {
           set
        
        
          set
        
        
           
           
        
        
           {
        
        
          
            {
             blogDataSet 
          
          
            =
          
          
             value;
            blogDataSet 
          
          
            =
          
          
             value;
             }
            }
          
        
        
           }
          }
        
      
    第七步:特殊处理,视图的嵌套。
EmailView视图和其他视图有些不一样,EmailView视图有DeckWorkspace,在DeckWorkspace中还必须显示两个子视图。这样就使数据的共享,WorkItem的访问存在少许差异。我们不妨首先来看SamrtRootWorkItem中显示EmailView的方法:
 private
      
      
         
      
      
        void
      
      
         ShowEmailView()
      
         
      
      
        private
      
      
         
      
      
        void
      
      
         ShowEmailView()
         
         
      
      
         {
      
      
        
          {
           IWorkspace workspace 
        
        
          =
        
        
           
        
        
          this
        
        
          .Workspaces[
        
        
          "
        
        
          deckWS_MainEmail
        
        
          "
        
        
          ];
          IWorkspace workspace 
        
        
          =
        
        
           
        
        
          this
        
        
          .Workspaces[
        
        
          "
        
        
          deckWS_MainEmail
        
        
          "
        
        
          ];
           emailView 
        
        
          =
        
        
           
        
        
          this
        
        
          .Items.AddNew
        
        
          <
        
        
          TestSmartPart.Emails.EmailView
        
        
          >
        
        
          (
        
        
          "
        
        
          EmailView
        
        
          "
        
        
          );
          emailView 
        
        
          =
        
        
           
        
        
          this
        
        
          .Items.AddNew
        
        
          <
        
        
          TestSmartPart.Emails.EmailView
        
        
          >
        
        
          (
        
        
          "
        
        
          EmailView
        
        
          "
        
        
          );
           workspace.Show(emailView);
          workspace.Show(emailView);
           
           if
        
        
           (emailWorkItem 
        
        
          ==
        
        
           
        
        
          null
        
        
          )
        
        
          if
        
        
           (emailWorkItem 
        
        
          ==
        
        
           
        
        
          null
        
        
          )
           
           
        
        
           {
        
        
          
            {
             emailWorkItem 
          
          
            =
          
          
             
          
          
            this
          
          
            .Items.AddNew
          
          
            <
          
          
            TestSmartPart.Emails.EmailWorkItem
          
          
            >
          
          
            (
          
          
            "
          
          
            EmailWorkItem
          
          
            "
          
          
            );
            emailWorkItem 
          
          
            =
          
          
             
          
          
            this
          
          
            .Items.AddNew
          
          
            <
          
          
            TestSmartPart.Emails.EmailWorkItem
          
          
            >
          
          
            (
          
          
            "
          
          
            EmailWorkItem
          
          
            "
          
          
            );
             }
            }
          
        
        
           emailWorkItem.State[
        
        
          "
        
        
          emailDataSet
        
        
          "
        
        
          ] 
        
        
          =
        
        
           
        
        
          new
        
        
           DataSet();
          emailWorkItem.State[
        
        
          "
        
        
          emailDataSet
        
        
          "
        
        
          ] 
        
        
          =
        
        
           
        
        
          new
        
        
           DataSet();
           ((DataSet)emailWorkItem.State[
        
        
          "
        
        
          emailDataSet
        
        
          "
        
        
          ]).ReadXml(
        
        
          "
        
        
          myEmails.xml
        
        
          "
        
        
          );
          ((DataSet)emailWorkItem.State[
        
        
          "
        
        
          emailDataSet
        
        
          "
        
        
          ]).ReadXml(
        
        
          "
        
        
          myEmails.xml
        
        
          "
        
        
          );
           emailWorkItem.Run();
          emailWorkItem.Run();
           }
          }
        
      
    
           我们发现TestSmartPart.Emails.EmailWorkItem被加入SamrtRootWorkItem的Items集合,deckWS_MainEmail这个Workspace也被加入SamrtRootWorkItem的Items集合。因此访问这些Workspace时,必须通过WorkItem.Parent.Workspaces[ ]来访问。代码如下:
      
    
 public
      
      
         
      
      
        class
      
      
         EmailWorkItem : WorkItem
      
        public
      
      
         
      
      
        class
      
      
         EmailWorkItem : WorkItem
         
         
      
      
         {
      
      
        
          {
           private
        
        
           EmailDetailView emailDetailView;
        
        
          private
        
        
           EmailDetailView emailDetailView;
           private
        
        
           EmailTitleView emailTitleView;
        
        
          private
        
        
           EmailTitleView emailTitleView;
           
           public
        
        
           
        
        
          override
        
        
           
        
        
          void
        
        
           Run()
        
        
          public
        
        
           
        
        
          override
        
        
           
        
        
          void
        
        
           Run()
           
           
        
        
           {
        
        
          
            {
             
             emailDetailView 
          
          
            =
          
          
             
          
          
            this
          
          
            .Items.AddNew
          
          
            <
          
          
            EmailDetailView
          
          
            >
          
          
            (
          
          
            "
          
          
            EmailDetailView
          
          
            "
          
          
            );
            emailDetailView 
          
          
            =
          
          
             
          
          
            this
          
          
            .Items.AddNew
          
          
            <
          
          
            EmailDetailView
          
          
            >
          
          
            (
          
          
            "
          
          
            EmailDetailView
          
          
            "
          
          
            );
             emailTitleView 
          
          
            =
          
          
             
          
          
            this
          
          
            .Items.AddNew
          
          
            <
          
          
            EmailTitleView
          
          
            >
          
          
            (
          
          
            "
          
          
            EmailTitleView
          
          
            "
          
          
            );
            emailTitleView 
          
          
            =
          
          
             
          
          
            this
          
          
            .Items.AddNew
          
          
            <
          
          
            EmailTitleView
          
          
            >
          
          
            (
          
          
            "
          
          
            EmailTitleView
          
          
            "
          
          
            );
             
             IWorkspace titleWorkspace 
          
          
            =
          
          
             
          
          
            this
          
          
            .Parent.Workspaces[
          
          
            "
          
          
            deckWS_EmailTitle
          
          
            "
          
          
            ];
            IWorkspace titleWorkspace 
          
          
            =
          
          
             
          
          
            this
          
          
            .Parent.Workspaces[
          
          
            "
          
          
            deckWS_EmailTitle
          
          
            "
          
          
            ];
             IWorkspace detailWorkspace 
          
          
            =
          
          
             
          
          
            this
          
          
            .Parent.Workspaces[
          
          
            "
          
          
            deckWS_EmailDetail
          
          
            "
          
          
            ];
            IWorkspace detailWorkspace 
          
          
            =
          
          
             
          
          
            this
          
          
            .Parent.Workspaces[
          
          
            "
          
          
            deckWS_EmailDetail
          
          
            "
          
          
            ];
             
             titleWorkspace.Show(emailTitleView);
            titleWorkspace.Show(emailTitleView);
             detailWorkspace.Show(emailDetailView);
            detailWorkspace.Show(emailDetailView);
             }
            }
          
        
        
           
           }
          }
        
      
    第八步:运行程序
            经过一些修改后,我们可以运行我们的例程,大家看看下面这个界面是不是像一个Portal啊?
      
      
         
      
    
      源代码下载地址:
      
        /Files/hyphappy/TestSmartPart.rar
      
      
    


 
					 
					