I have been working my way through Jeremy Miller's excellent Build Your Own CAB Series (which would be even better if he felt like finishing!) and was very interested by the article on controlling menus with Microcontrollers.
After reading it and writing a version of it myself, I came to the conclusion that some parts of it seem to be wrong. All of the permissioning is done based on the menu items which fire ICommands, and several menu items could use the same ICommand. This means that you need to use the interface something like this:
Now to me this seems somewhat wrong, I would rather have something like this:
So I decided to have a go at re-working it to my liking. To start with we have the mandatory ICommand interface:
Then a class that manages the actual ICommand and its menuitem(s):
As you can see, the Dispose Method is used to allow for handlers to be removed, otherwise the objects might be hanging around longer than they should be. We also have a list of menu items that this command controls, and a list of roles that the command is available to.
Next we have the class that holds the state of each menu item, which is generic to allow the end user to use whatever they wish to identify each menu item:
Finally we have the Manager class which stitches the whole lot together with a health dollop of Fluent Interfaces. We have a unique list of Commands (as I wrote this in VS2005, I just had to make a unique List class, rather than use a dictionary of CommmandItem and Null) and a sub class which provides the Fluent Interface to the manager. (IDisposeable parts have been trimmed out for brevity, it's just contains a loop that disposes all child objects).
In my test application I have a file containing my menuCommands and an Enum used for identification:
And in the main form I have this code. The Thread Principle is used for the roles, and the actual roles could (should) be loaded from a database or anywhere other than hard coded constants of course.
The state object is used to enable and disable menu items and could be wrapped in another object if it needed to be exposed further than the form.