More Detail On Workspaces And SmartParts (Introduction To The CAB/SCSF Part 16)
2014-09-26 17:22
525 查看
Introduction
Part 15 of this series of articles explained SmartParts
in the CAB, and gave a very brief introduction to Workspaces. This article will continue with the same topics. In particular we will look in more detail at Workspaces.
Workspaces Recap
Part 15 explained the SmartParts can be most easily thought of as user controls or views in a composite application block application.
Part 15 also explained that Workspaces are just controls that allow other controls (SmartParts) to be laid out within them, and differ from other container controls in that they interact with other objects in the CAB in a predefined way. In particular there
is a Workspaces collection on any WorkItem, and they have a Show method that shows a SmartPart.
User Interface Design for Business Applications
In an earlier blog posting on user interface design I discussed some of the possible
user interface designs for applications that have to display multiple different screens of data. A common design for these applications is to have a tabbed client area for the screens, together with a tree-based window manager of some kind. An alternative
is an Outlook-style interface, again possibly with a tree window manager, but dispensing with tabs at the top of the screen. Clearly both of these designs are very similar: we click on a tab or double-click in a tree and our screen gets displayed in a predefined
part of the screen.
One thing to notice with both of these designs is that after we have displayed a client screen for the first time we won’t usually close it again. When other screens are displayed our first screen will stay in memory. It will retain the state it was displaying
the last time the user interacted with it. When the user requests to see the screen again it will just be brought to the front.
So we have a collection of objects (our screens) with persistent state whilst the application is running. We may create all of these screens at start-up. However more usually we’ll create a screen the first time the user requests it, and then redisplay it the
second time it is requested (a sort of lazy initialization). Note that at any given time many of the screens in the collection may not actually be displayed at all.
Building User Interfaces for Business Applications
Of course it is easy enough to create an application of this kind using Windows Forms standard controls. However, there’s some infrastructure code that we are going to have to write. We need:
some means of caching our screens collection
a way of allowing new screens to be added to the screens collection
a method of displaying a screen when it is requested for the first time
a method of redisplaying the appropriate screen in response to the appropriate request
We’ll also want to make sure we control the scope of our screens carefully so that they can’t be accessed from anywhere in the code. As we all know, global singletons (or global variables of any kind) are a bad thing.
The good news is that Workspaces and SmartParts do all this for us. What’s more they do it in a very simple way.
Workspaces – the IWorkspace Interface
All Workspaces implement the IWorkspace interface. This is the interface we are meant to use to interact with our Workspaces: usually we don’t need any more functionality than this interface provides as we shall see.
The IWorkspace interface has a number of useful methods. In general these behave as explained below, although each type of Workspace is free to implement them in its own way:
When this method is called, if the SmartPart passed as a parameter has not previously been shown in this Workspace it will be loaded and then activated. If it has already been shown and not been closed (i.e. if it is in the Workspace’s SmartParts collection)
it will just be activated. Usually ‘activated’ means brought to the front and made into the ActiveSmartPart.
If the object is in the Workspace’s SmartParts collection it will be activated as described above. If it’s not in that collection then an ArgumentException will be thrown.
Hides the SmartPart (sends it to the back usually), but leaves it in the Workspace’s SmartParts collection. The next control in the Workspace will usually be activated (made into the ActiveSmartPart). What ‘next’ means here varies by Workspace.
Hides the SmartPart and also removes it from the SmartParts collection. The next control in the Workspace will usually be activated.
IWorkspace also has a property ActiveSmartPart, which returns the active SmartPart if there is one. As discussed in part 15 Workspaces have a SmartParts collection, and the IWorkspace interface has a SmartParts property that lets us access this (it returns
a ReadOnlyCollection<object>).
IWorkspace also has events SmartPartActivated and SmartPartClosing. You can probably guess when these get fired.
There are also some methods to deal with SmartPartInfo on IWorkspace. I’ll discuss SmartPartInfo below.
Workspaces – Aside on how the Supporting Classes Work
The core functionality of IWorkspace is encapsulated in a class called, appropriately, Workspace. This is an abstract base class that all Workspaces are expected to inherit from. It implements IWorkspace so the individual Workspace classes don’t have to (since
they inherit the interface from Workspace).
The base class gives basic implementations of the members of IWorkspace, and also handles things like caching the active smart part, tracking the SmartParts collection, and raising the right events at the right time.
Whilst the way the supp
a972
orting classes work is quite interesting, you don’t need to know it in any detail to use the Workspace classes. The exception to this is if you want to write your own custom Workspace class, in which case you will need to get to grips
with them in more detail. Writing your own custom Workspaces is beyond the scope of these articles for now.
Further Aside on Multiple Inheritance in C#
The Workspace classes also demonstrate a method of achieving a kind of multiple inheritance in C#. This is done by composition, using a class called WorkspaceComposer and an interface called IComposableWorkspace. It’s needed because certain Workspace classes
(e.g. TabWorkspace) already inherit a Control class to give their basic functionality (in the case of TabWorkspace this is TabControl). As we know, in .NET a class can’t directly inherit more than one other class.
It is not my intention in these articles to actually discuss the underlying code in the Composite Application Block in any detail. The aim of these articles is to let you use the CAB as a black box component. But the WorkspaceComposer is particularly interesting
since it shows us a pattern for achieving multiple inheritance (albeit messily) in C#. If you are interested the code is in the Microsoft.Practice.CompositeUI.SmartParts namespace in the Microsoft.Practices.CompositeUI component.
SmartPartInfo
As we have seen the normal Show method on the IWorkspace interface only lets you pass the SmartPart you want to show as a parameter. There may be other information that the CAB framework will need to know to show your SmartPart correctly. For example, in a
TabWorkspace you need to provide the text for a new tab somehow. In a ZoneWorkspace you need to tell the CAB which particular zone the SmartPart will be displayed in.
This problem is solved by passing an additional object to the Show method:
This additional object implements the interface ISmartPartInfo, which has Title and Description properties. It’s the Title property that’s used to set the tab page title in the TabWorkspace.
The smartPartInfo object can contain any additional information we require. For example, for ZoneWorkspaces it contains the name of the zone in which the SmartPart will be displayed.
The IWorkspace interface also has a method to directly apply the information in a SmartPartInfo object to a SmartPart that has already been displayed:
In a ZoneWorkspace this can be used to change the zone where a SmartPart is shown in, for example. The next article in this series will give some examples of this.
Conclusion
This article has discussed some of the theory behind Workspaces, and shown the basic interfaces. Part 17 in this series of articles will discuss the various types of Workspace that are available in the CAB, and give some code examples of how to use them.
Part 15 of this series of articles explained SmartParts
in the CAB, and gave a very brief introduction to Workspaces. This article will continue with the same topics. In particular we will look in more detail at Workspaces.
Workspaces Recap
Part 15 explained the SmartParts can be most easily thought of as user controls or views in a composite application block application.
Part 15 also explained that Workspaces are just controls that allow other controls (SmartParts) to be laid out within them, and differ from other container controls in that they interact with other objects in the CAB in a predefined way. In particular there
is a Workspaces collection on any WorkItem, and they have a Show method that shows a SmartPart.
User Interface Design for Business Applications
In an earlier blog posting on user interface design I discussed some of the possible
user interface designs for applications that have to display multiple different screens of data. A common design for these applications is to have a tabbed client area for the screens, together with a tree-based window manager of some kind. An alternative
is an Outlook-style interface, again possibly with a tree window manager, but dispensing with tabs at the top of the screen. Clearly both of these designs are very similar: we click on a tab or double-click in a tree and our screen gets displayed in a predefined
part of the screen.
One thing to notice with both of these designs is that after we have displayed a client screen for the first time we won’t usually close it again. When other screens are displayed our first screen will stay in memory. It will retain the state it was displaying
the last time the user interacted with it. When the user requests to see the screen again it will just be brought to the front.
So we have a collection of objects (our screens) with persistent state whilst the application is running. We may create all of these screens at start-up. However more usually we’ll create a screen the first time the user requests it, and then redisplay it the
second time it is requested (a sort of lazy initialization). Note that at any given time many of the screens in the collection may not actually be displayed at all.
Building User Interfaces for Business Applications
Of course it is easy enough to create an application of this kind using Windows Forms standard controls. However, there’s some infrastructure code that we are going to have to write. We need:
some means of caching our screens collection
a way of allowing new screens to be added to the screens collection
a method of displaying a screen when it is requested for the first time
a method of redisplaying the appropriate screen in response to the appropriate request
We’ll also want to make sure we control the scope of our screens carefully so that they can’t be accessed from anywhere in the code. As we all know, global singletons (or global variables of any kind) are a bad thing.
The good news is that Workspaces and SmartParts do all this for us. What’s more they do it in a very simple way.
Workspaces – the IWorkspace Interface
All Workspaces implement the IWorkspace interface. This is the interface we are meant to use to interact with our Workspaces: usually we don’t need any more functionality than this interface provides as we shall see.
The IWorkspace interface has a number of useful methods. In general these behave as explained below, although each type of Workspace is free to implement them in its own way:
void Show(object smartPart)
When this method is called, if the SmartPart passed as a parameter has not previously been shown in this Workspace it will be loaded and then activated. If it has already been shown and not been closed (i.e. if it is in the Workspace’s SmartParts collection)
it will just be activated. Usually ‘activated’ means brought to the front and made into the ActiveSmartPart.
void Activate(object smartPart)
If the object is in the Workspace’s SmartParts collection it will be activated as described above. If it’s not in that collection then an ArgumentException will be thrown.
void Hide(object smartPart)
Hides the SmartPart (sends it to the back usually), but leaves it in the Workspace’s SmartParts collection. The next control in the Workspace will usually be activated (made into the ActiveSmartPart). What ‘next’ means here varies by Workspace.
void Close(object smartPart)
Hides the SmartPart and also removes it from the SmartParts collection. The next control in the Workspace will usually be activated.
IWorkspace also has a property ActiveSmartPart, which returns the active SmartPart if there is one. As discussed in part 15 Workspaces have a SmartParts collection, and the IWorkspace interface has a SmartParts property that lets us access this (it returns
a ReadOnlyCollection<object>).
IWorkspace also has events SmartPartActivated and SmartPartClosing. You can probably guess when these get fired.
There are also some methods to deal with SmartPartInfo on IWorkspace. I’ll discuss SmartPartInfo below.
Workspaces – Aside on how the Supporting Classes Work
The core functionality of IWorkspace is encapsulated in a class called, appropriately, Workspace. This is an abstract base class that all Workspaces are expected to inherit from. It implements IWorkspace so the individual Workspace classes don’t have to (since
they inherit the interface from Workspace).
The base class gives basic implementations of the members of IWorkspace, and also handles things like caching the active smart part, tracking the SmartParts collection, and raising the right events at the right time.
Whilst the way the supp
a972
orting classes work is quite interesting, you don’t need to know it in any detail to use the Workspace classes. The exception to this is if you want to write your own custom Workspace class, in which case you will need to get to grips
with them in more detail. Writing your own custom Workspaces is beyond the scope of these articles for now.
Further Aside on Multiple Inheritance in C#
The Workspace classes also demonstrate a method of achieving a kind of multiple inheritance in C#. This is done by composition, using a class called WorkspaceComposer and an interface called IComposableWorkspace. It’s needed because certain Workspace classes
(e.g. TabWorkspace) already inherit a Control class to give their basic functionality (in the case of TabWorkspace this is TabControl). As we know, in .NET a class can’t directly inherit more than one other class.
It is not my intention in these articles to actually discuss the underlying code in the Composite Application Block in any detail. The aim of these articles is to let you use the CAB as a black box component. But the WorkspaceComposer is particularly interesting
since it shows us a pattern for achieving multiple inheritance (albeit messily) in C#. If you are interested the code is in the Microsoft.Practice.CompositeUI.SmartParts namespace in the Microsoft.Practices.CompositeUI component.
SmartPartInfo
As we have seen the normal Show method on the IWorkspace interface only lets you pass the SmartPart you want to show as a parameter. There may be other information that the CAB framework will need to know to show your SmartPart correctly. For example, in a
TabWorkspace you need to provide the text for a new tab somehow. In a ZoneWorkspace you need to tell the CAB which particular zone the SmartPart will be displayed in.
This problem is solved by passing an additional object to the Show method:
void Show(object smartPart, ISmartPartInfo smartPartInfo)
This additional object implements the interface ISmartPartInfo, which has Title and Description properties. It’s the Title property that’s used to set the tab page title in the TabWorkspace.
The smartPartInfo object can contain any additional information we require. For example, for ZoneWorkspaces it contains the name of the zone in which the SmartPart will be displayed.
The IWorkspace interface also has a method to directly apply the information in a SmartPartInfo object to a SmartPart that has already been displayed:
void ApplySmartPartInfo(object smartPart, ISmartPartInfo smartPartInfo)
In a ZoneWorkspace this can be used to change the zone where a SmartPart is shown in, for example. The next article in this series will give some examples of this.
Conclusion
This article has discussed some of the theory behind Workspaces, and shown the basic interfaces. Part 17 in this series of articles will discuss the various types of Workspace that are available in the CAB, and give some code examples of how to use them.
相关文章推荐
- Introduction To SmartParts And Workspaces (Introduction To CAB/SCSF Part 15)
- Business Modules And Interfaces In The SCSF Smart Client Solution (Introduction To CAB/SCSF Part 19)
- Model-View-Presenter: Variations On The Basic Pattern (Introduction To CAB/SCSF Part 24)
- More On UIExtensionSites (Introduction To CAB/SCSF Part 14)
- Model-View-Presenter Using The Smart Client Software Factory (Introduction To CAB/SCSF Part 25)
- Model-View-Presenter: Why We Need It And The Basic Pattern (Introduction To CAB/SCSF Part 23)
- SCSF Business Modules: Start Up And The ControlledWorkItem (Introduction To CAB/SCSF Part 20)
- Introduction To The Smart Client Software Factory (CAB/SCSF Part 18)
- Commands In The CAB (Introduction To CAB/SCSF Part 10)
- Events In The CAB (Introduction To CAB/SCSF Part 12)
- Workspace Types (Introduction To The CAB/SCSF Part 17)
- SCSF - Part 7 Introduction to Services in the CAB
- Introduction To Events In The CAB (Introduction To CAB/SCSF Part 11)
- Introduction To UIExtensionSites (Introduction To The CAB/SCSF Part 13)
- Foundational Modules And Names As Constants (Intro To CAB/SCSF Part 21)
- An Introduction to SELinux on CentOS 7 – Part 2: Files and Processes
- Model-View-Controller Explained (Introduction To CAB/SCSF Part 22)
- SCSF - Part 8 Creating and Using Services in the CAB
- [旧稿]How To Add Simple "Install WebPart" Menu to the Right Click On a CAB File
- Loadrunner连接负载机失败,提示"Failed to connect to the load generator.Check the output window for more detail