Best method to switch between different WorkItems

Topics: CAB & Smart Client Software Factory
Feb 15, 2006 at 12:46 PM
originally posted by: sklett

Currently I have two work items:
- InventoryWorkItem with it's single view
- AddNewInventoryItemWorkItem which is nested in InventoryWorkItem.

I have added 2 MenuItems to my shell's MainMenu:
- Review -- When a user clicks this, I want to activate the InventoryWorkItem
- Add new item -- When a user clicks this, I want to activate the AddNewInventoryItemWorkItem


I have the latter working by doing this:
1) add a command for the menuItem
2) add an event handler in the InventoryWorkItem's view and a CommandHandler
3) the above event handler then calls the view's controller method AddNewItem
4) controller's AddNewItem method calls InventoryWorkItem method AddNewItem
5) InventoryWorkItem's method AddNewItem creates a new AddNewInventoryItemWorkItem and calls it's Show() method

This works well, I'm not sure if it's the "correct" way, but from pouring over the sample projects, this is what I extrapolated from them.

Now onto the former, this one I'm having a hard time with. If I want to switch between 2 different WorkItems based on UIElement generated events... what view should implement the handler? If I'm currently working with view A from WorkItem A and I want to switch to View A from WorkItem B... how do I do that?

When my application starts, I show InventoryWorkItem
If a user clicks on the "Add New Item" MenuItem in the shell, I activate AddNewInventoryItemWorkItem

now, if the user clicks on the "Review" MenuItem in the shell, I want to activate InventoryWorkItem again, how do I do that?

I'm very confused, any help would be SOOooo nice, please.

Thank you for reading,
Steve
Feb 15, 2006 at 3:21 PM
originally posted by: ChrisHolmes

"view A from WorkItem A and I want to switch to View A from WorkItem B... how do I do that?"


One way to accomplish this is to use a DeckWorkSpace. When you instantiate a WorkItemA it creates its own version of the View and runs it in the DeckWorkspace. Then when you want to run WorkItemB with the same view, it's really creating a new View and running that in the DeckWorkspace as well. Then you would setup your menu commands so that the active WorkItem has its view being shown in the DeckWorkspace.

"now, if the user clicks on the "Review" MenuItem in the shell, I want to activate InventoryWorkItem again, how do I do that?"


When you create a new WorkItem and add it to the current WorkItem's Item list, you have the option to name it with a string ID.

MyWorkItem workItem = this.Items.AddNew<MyWorkItem>("MyWorkItemNameID");

Now, using that string you can retrieve that WorkItem from the current WorkItem's list, like so:

MyWorkItem workItem = this.Items.Get<MyWorkItem>("MyWorkItemNameID");

If you've given your WorkItem a reference to the View it creates (SmartPart) then you can expose that View as a property of the WorkItem. This allows you to Show() or Hide() it in the DeckWorkspace, like so:

this.Workspaces"MyDeckWorkspace".Show(workItem.View);

The View should have been created when you created the WorkItem for the first time, using the AddNew<>. So the View exists and is a property of the WorkItem. It gets shown in the DeckWorkspace and can be reshown any time you like.

Hope that helps!
Feb 16, 2006 at 7:48 AM
originally posted by: sklett

Hi Chris, thank you for the response!

I'm getting a better grasp of the relationships and interactions, your post helped.

I find myself still with one question that I can't answer. What view should I make responsible to handle module-wide shell events? In other words, to use my example again; I have 2 MenuItems, I need to have each one "activate" and "show"
it's respective work item and default view. The problem arises when I start to implement the CommandHandler and realize I don't know what file to place it in.

    • OK, I stopped in the middle of writing this and messed around a little more. (You know how typing something can make you think about it a different way?) - anyways, I realized that any view can respond to an Command, not just the active one. So what I did real quick (I'm looking for approval on this):
- added the CommandHandler for each MenuItem click in the View that it is intended to show. So MenuItemA's CommandHandler is in ViewA and MenuItemB's CommandHandler is in ViewB
- then I created a Controller method that would call a WorkItem method that would finally call Show(). For example, ViewA CommandHandler calls ControllerA::ShowViewA() which calls WorkItemA::ShowView_A() which as a single line of code: Show(MyMainWorkspace)

So... is that the intended control flow? Am I utilizing the pattern and CAB correctly?

Thanks for reading, I hope my question is clear enough.
-Steve
Feb 16, 2006 at 8:08 AM
originally posted by: ChrisHolmes

Sklett,

My confusion at this point stems from knowing where your MenuItems are contained. Are they in the individual views, or are they part of the Shell?
Feb 16, 2006 at 8:11 AM
originally posted by: sklett

Sorry, unclear again.

They are UIElements in the shell.
Feb 16, 2006 at 8:25 AM
originally posted by: ChrisHolmes

Ok, then you can circumvent the view/controller.

What you really need to have happen is two things:

First, you need the UIElement MenuItems in the Shell to publish Commands and tie those commands to the MenuItem's click event (or whatever event you're after).

Second, you need to have the WorkItem in control of the DeckWorkSpace handle the Command, because it is the thing that will perform the Show().

The Views and Controllers in your WorkItem don't need to know about the Command. They don't need to handle it.

If you're using the DeckWorkSpace to manage different Views then whatever WorkItem is in control of that DeckWorkSpace is the WorkItem that needs to handle the Command (in my current application, for instance, this is the RootWorkItem which has control of the DeckWorkSpace).

Does that help?
Feb 16, 2006 at 8:45 AM
originally posted by: sklett

Yes, that does help and of course seems like the logical approach. I have added the code to my ModuleInit class and it works just fine. Thanks for the suggestion, I just needed a little guidance, confidence is loooow in these initial days of learning the CAB :)

Thanks again for the help, I appreciate it.
-Steve
Feb 16, 2006 at 8:48 AM
originally posted by: ChrisHolmes

"confidence is loooow in these initial days of learning the CAB :) "

I know how ya feel :-)