?

Log in

No account? Create an account
DevLynx

Creating Dynamic UIElements

There is some controversy in the CAB development community about the usefulness of Commands and UIExtensionSites. You can see some of the discussions here, here, and here (and in comments from this journal here). I am still in the "commands and UIExtensionSites are good" camp; but I am willing to bypass the CAB philosophy if I find a requirement which I cannot implement using these CAB tools. One of the suggestions in the aforementioned discussions was to only use commands for menu items and toolstrip items. This seems to make a lot of sense to me. However, this still means that we need to handle galleries, menus and toolbars — some of which could be created dynamically.

I am using "dynamic" in this discussion to mean a set of items where the number of items is not known at compile time. Furthermore, the items within this dynamic set will call the same method; individual dynamic items may pass different parameters to the method. Two examples of this are:
  • Developer Express skins: New skins are added on occasion and we don't want to recode for each new skin. The dynamic information passed is the skin name.
  • Fonts: We cannot anticipate how many or which fonts will be on the end user machine. The dynamic information passed can be either the font name or an instance of the font itself.
How can we accomplish this dynamic creation and still keep somewhat close to the CAB philosophy?

To implement dynamic UIElements, we have to abandon CAB commands and embrace CAB Events. CAB commands are intentionally designed to hide all information about which UIElement was pressed. Events allow us to pass additional information with the event, a requirement since multiple UIElements will call the same method to accomplish their work.

I have created a DynamicCommandEventLink class which is used to pass the necessary information. This class includes the event topic name that this particular dynamic item will fire. It also contains an object for the dynamic data to be passed to the event. An instance of this class is passed in the Tag property of the menu item, gallery item, etc. I then created special extension sites which handle the DynamicCommandEventLink. These include RibbonGalleryDynamicUIAdapter and RibbonGalleryGroupDynamicUIAdapter working in tandem; and the BarLinksCollectionDynamicUIAdapter which handles menus and toolbars.

I imagine that some will say that all of this can be accomplished via directly instantiating a menu or gallery bypassing the CAB framework. This is true for most situations. But if someone directly instantiates a menu to which a module later needs to add items, we have lost the decoupling that the CAB provides. The dynamic UIElements gives the developer a decoupling choice.

You can see the code within the CAB DevExpress Extension Kit. Examples of how to use them are supplied in the BankTeller demo application where both the skins ribbon gallery and an optional skins menu use dynamic UI adapters.

dlx

Comments

CAB Commands

Hello, thanks for your post and your extensions!
I must say that I like commands and I have not threw them away. For simple "command" items they are very useful. Especially I like command status updating - I have created simple CommandStatusService, which on Application.Idle calls registered handlers. Each of handlers returns status of appropriate command. This is very easy way how to maintain status of Save, MoveTo, Print and similar commands. The idea of status pooling comes from Delphi Actions list, I believe you know it :-)

But you are right - the impossibility of transfering user data along with command is very unconfortable. I agree that using event is the only reansoable way. But events do not have Status - it is pity.

One thing to mention: DevExpress saves me many many days of writing and debugging service for MDI toolbar context switching. What I mean is "how to switch toolbar context when application context changes". Solution was relativelly simple. Each SmartPart carries its own ribbon, which is in runtime merged with MDI window's ribbon and MDI window ribbon is merged with main ribbon. Works like a charm in the complicated CAB world.

Karel

Re: CAB Commands

Karel,

I remember so well when I first played with Delphi Action Lists; such a pleasure to work with at that time :-) When you told me about your RibbonService I figured you had tossed commands out completely. I'm glad that you are still using them.

I have been working on pieces of my ShellApp and I think you are much farther in your understanding of CAB then I am. I may tap into that knowledge one of these days :-)

Thanks, as always, for your comments.

dlx