您的位置:首页 > 其它

Smart Client Software Factory:简单的新建一个界面并显示出来

2011-05-11 14:59 441 查看
首先在VS.NET上新建一个Smart Client Software Factory的解决方案.最初自动生成的是一个Source文件夹,然后是一个子文件夹名为Infrastructure



几个Infrastructure(基础设施)项目

Infrastructure.Interface

Infrastructure.Layout

Infrastructure.Library

Infrastructure.Module



还有一个启动项目Shell,Shell下的ShellForm为整个程序的入口点,这个shellForm并不是程序的最终界面,只是一个"壳",运行时上面的内容是动态加载上去的

研究一下它的代码

Public Sub New()
        InitializeComponent()
        _layoutWorkspace.Name = WorkspaceNames.LayoutWorkspace
    End Sub




WorkspaceNames.LayoutWorkspace 这个workspace的概念是什么,以后再研究



那么要往这个"壳"上加上你自己的View,就要用SCSF的模板先新建一个Module项目,有两种module可以选择,bussiness和functional

Functional Module -- 只是给其它模块提供一些服务,并不实现一个Use-case,不包含一个WorkItem

Business Module -- 实现一系列相关的用例,包含WorkItems。

我这里选的是bussiness类型,菜单上面有些选择项,可以选择生成对应的单元测试项目和接口项目。



生成Module项目以后,会生成几个文件夹Constants,Services,Views。另外还有两个类ModuleController,ModuleInitializer

这里先只关注ModuleController这个类,它继承自WorkItemController,WorkItemController是一个什么类呢?它来自Infrastructure.Interface下,看看它的源代码



Imports Microsoft.Practices.CompositeUI
Imports SmartClient.Infrastructure.Interface.Services
''' <summary>
''' Base class for a WorkItem controller.
''' </summary>
Public MustInherit Class WorkItemController
    Implements IWorkItemController
    Private _workItem As WorkItem
    ''' <summary>
    ''' Gets or sets the work item.
    ''' </summary>
    ''' <value>The work item.</value>
    <ServiceDependency()> _
    Public Property WorkItem() As WorkItem
        Get
            Return _workItem
        End Get
        Set(ByVal value As WorkItem)
            _workItem = value
        End Set
    End Property
    Public ReadOnly Property ActionCatalogService() As IActionCatalogService
        Get
            Return _workItem.Services.Get(Of IActionCatalogService)()
        End Get
    End Property
	''' <summary>
	''' Creates and shows a smart part on the specified workspace.
	''' </summary>
	''' <typeparam name="TView">The type of the smart part to create and show.</typeparam>
	''' <param name="workspaceName">The name of the workspace in which to show the smart part.</param>
	''' <returns>The new smart part instance.</returns>
	Protected Overridable Function ShowViewInWorkspace(Of TView)(ByVal workspaceName As String) As TView
		Dim view As TView = WorkItem.SmartParts.AddNew(Of TView)()
		WorkItem.Workspaces(workspaceName).Show(view)
		Return view
	End Function
	''' <summary>
	''' Shows a specific smart part in the workspace. If a smart part with the specified id
	''' is not found in the <see cref="WorkItem.SmartParts"/> collection, a new instance
	''' will be created; otherwise, the existing instance will be re used.
	''' </summary>
	''' <typeparam name="TView">The type of the smart part to show.</typeparam>
	''' <param name="viewId">The id of the smart part in the <see cref="WorkItem.SmartParts"/> collection.</param>
	''' <param name="workspaceName">The name of the workspace in which to show the smart part.</param>
	''' <returns>The smart part instance.</returns>
	Protected Overridable Function ShowViewInWorkspace(Of TView)(ByVal viewId As String, ByVal workspaceName As String) As TView
		Dim view As TView
		If WorkItem.SmartParts.Contains(viewId) Then
			view = WorkItem.SmartParts.Get(Of TView)(viewId)
		Else
			view = WorkItem.SmartParts.AddNew(Of TView)(viewId)
		End If
		WorkItem.Workspaces(workspaceName).Show(view)
		Return view
	End Function
	
    Public Overridable Sub Run() Implements IWorkItemController.Run
    End Sub
End Class




它基本就是在操纵WorkItem和IView这两个对象,这里要搞清几个概念

Workspace是什么?SmartParts是什么?



先看微软官方对SmartParts的解释

Microsoft’s CAB documentation defines a SmartPart as ‘a view of data (in the MVC pattern) such as a control, a Windows Form, or a wizard page

微软的CAB文档中把SmartPart 定义为数据的视图(在MVC模式下) 比如控件,Windows 窗体,向导页

姑且就把它看成是控件吧,或者应该说它是除了容器以外的控件



再看微软官方对Workspace的解释

The components that encapsulate a particular visual layout of controls and SmartParts, such as within tabbed pages

一个特定的组件,封装控制视觉布局与SmartParts,比如"标签页"

从字面上已经能解释,Workspace实际跟我们平时项目中用到的容器控件类似,都是一个承载其它控件的容器

Workspaces are themselves controls that allow other controls to be laid out within them,In particular they are designed to allow SmartParts to be laid out within them.

Workspaces它们自身允许其它的控件放进它们之中,特别是它们被设计为让SmartParts放进它们中.

看,这句话已经说得够明白的了。



Workspaces与普通容器控件的不同就是,它们利用了CAB依赖注入容器(Workitmes)

我们可以在Workspaces集合中用AddNew关键字创建一个Workspace,然而我们并不需要这么做。可以拖放一个Workspace到屏幕,ObjectBuilder 会自动的识别这个Workspace,并把它加入到适当的集合中



Workspace分为好几种,具体可以看以下页面

http://richnewman.wordpress.com/2007/11/24/workspace-types-introduction-to-the-cabscsf-part-17/



具体概念回顾,参考我以前的文章

http://blog.csdn.net/lee576/archive/2011/05/03/6386857.aspx

以Office Excel来举例就清楚了,它们在Excel中各自扮演的角色一目了然.



回到主线上来,WorkItem就是业务逻辑,WorkItemController就是业务逻辑控制器啦.它所做的工作很简单,避免View与WorkItem之间的耦合,View不知道WorkItem的存在,WorkItem也不认识View,他们都只与WorkItemController发生耦合.从代码来看,WorkItemController的工作无非就是告诉View,工作在哪个Workspace之下,这就是经典的MVC模式,不是吗?



WorkItem:A runtime container of the objects and services used by a discrete part of a CAB application. Think of it as a logical sub-process or sub-application. It is the basic unit of software scoping in a CAB application. Your business logic lives in one or more WorkItems.
英文的头一句解释似乎很抽象,"CAB程序的一个独立部分,用于对象和服务的运行时容器."






说回我们刚刚生成的这个ModuleController类,如果我们想在主窗体中显示我们自己的view怎么做呢?

首先我们在Views文件夹下右键选择SCSF的模板菜单,选择Add View(with presenter)

这里我们给View起名叫Demo,会自动生成三个文件,DemoView.vb,DemoViewPresenter.vb,IDemoView.vb

哈,典型的MVP模式啊!

DemoViewPresenter类继承自Presenter基类,Presenter又干了些什么呢

Imports Microsoft.Practices.CompositeUI
Imports System
Imports Microsoft.Practices.CompositeUI.SmartParts
Public MustInherit Class Presenter(Of TView)
    Implements IDisposable
    Private _view As TView
    Private _workItem As WorkItem
    Private _disposed As Boolean = False
    Public Property View() As TView
        Get
            Return _view
        End Get
        Set(ByVal value As TView)
            _view = value
            OnViewSet()
        End Set
    End Property
    <ServiceDependency()> _
    Public Property WorkItem() As WorkItem
        Get
            Return _workItem
        End Get
        Set(ByVal value As WorkItem)
            _workItem = value
        End Set
    End Property
    Protected Overridable Sub CloseView()
        Dim locator As Services.IWorkspaceLocatorService = WorkItem.Services.Get(Of Services.IWorkspaceLocatorService)()
        Dim wks As IWorkspace = locator.FindContainingWorkspace(WorkItem, View)
        If Not wks Is Nothing Then
            wks.Close(View)
        End If
    End Sub
    Public Overridable Sub OnViewReady()
    End Sub
    Protected Overridable Sub OnViewSet()
    End Sub
    
    Public Overridable Sub OnCloseView()
    End Sub
    ''' <summary>
    ''' See <see cref="System.IDisposable.Dispose"/> for more information.
    ''' </summary>
    Public Sub Dispose() Implements IDisposable.Dispose
        If Not _disposed Then
			Dispose(True)
			GC.SuppressFinalize(Me)
		End If
    End Sub
    ''' <summary>
    ''' Called when the object is being disposed or finalized.
    ''' </summary>
    ''' <param name="disposing">True when the object is being disposed (and therefore can
    ''' access managed members); false when the object is being finalized without first
    ''' having been disposed (and therefore can only touch unmanaged members).</param>
    Protected Overridable Sub Dispose(ByVal disposing As Boolean)
		If disposing Then
			If Not _workItem Is Nothing Then
				If Not Me.View Is Nothing Then
					OnCloseView()
					_workItem.Items.Remove(Me.View)
				End If
 
				_workItem.Items.Remove(Me)
			End If
		End If
		
		_disposed = True
    End Sub
End Class


设置当前的Workitem,当前的View,把它们关联起来,然后在View的三个生命周期中放上了三个虚函数,目的是便于在子类中重写达到扩展的目的,这就是事件的支持。最后它还负责析构自身,及移除workitem中的view.为什么要移除view呢?无非是为了释放掉资源,本来View就是动态加上去的。在Close的时候就移除view与workitem的关系。



最后,如果我们要把刚刚新建的Demo加到主窗体中怎么做呢?

回到ModuleController类,写上



Private Sub AddViews()
        'TODO: create the Module views, add them to the WorkItem and show them in 
        'a Workspace. 
		' To create and add a view you can customize the following sentence
		' ShowViewInWorkspace(Of SampleView)(WorkspaceNames.SampleWorkspace)
        ShowViewInWorkspace(Of DemoView)(WorkspaceNames.LayoutWorkspace)
    End Sub




这是把View设置到一个Workspace上面,WorkspaceNames.LayoutWorkspace

WorkspaceNames是个自定义的常量类



Public Class WorkspaceNames
        Public Const LayoutWorkspace As String = "LayoutWorkspace"
        Public Const ModalWindows As String = "ModalWindows"
        Public Const LeftWorkspace As String = "LeftWorkspace"
        Public Const RightWorkspace As String = "RightWorkspace"
    End Class




Public Const LayoutWorkspace As String = "LayoutWorkspace"

这个相当于是Microsoft.Practices.CompositeUI.WinForms.DeckWorkspace



证据在这里,ShellForm.Designer.vb里面

Private Sub InitializeComponent()
        Me._layoutWorkspace = New Microsoft.Practices.CompositeUI.WinForms.DeckWorkspace
        Me.SuspendLayout()
        '
        '_layoutWorkspace
        '
        Me._layoutWorkspace.Dock = System.Windows.Forms.DockStyle.Fill
        Me._layoutWorkspace.Location = New System.Drawing.Point(0, 0)
        Me._layoutWorkspace.Name = "_layoutWorkspace"
        Me._layoutWorkspace.Size = New System.Drawing.Size(698, 516)
        Me._layoutWorkspace.TabIndex = 0
        Me._layoutWorkspace.Text = "_layoutWorkspace"
        '
        'ShellForm
        '
        Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
        Me.ClientSize = New System.Drawing.Size(698, 516)
        Me.Controls.Add(Me._layoutWorkspace)
        Me.Name = "ShellForm"
        Me.Text = "ShellForm"
        Me.ResumeLayout(False)
    End Sub




还有其它几个常量,具体都是在ShowViewInWorkspace里使用,以后再弄清楚细节
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: