ActiveAware Views and Commands

It occurred to me after a recent advisory board call that we haven't done a good job of communicating the scenarios that prompted the development of ActiveAware views and commands. Let me describe this functionality in terms of the ability to "Save All" versus "Save Active".

Save All:

The ability to "Save All" describes saving ALL elements of an application that have registered as "saveable". My application could have orders, customers, inventory, and other entities that could be edited and therefore need to be saved. Let's say my application allows me to edit multiple orders, customers, and inventory items simultaneously. If I were to invoke the SaveAll command, I would expect that every edited order, customer, and inventory item gets saved. In addition, since WPF commands provide a mechanism for commands to communicate enablement from the command handler to the invoker, I would also like my SaveAll command invokers to be enabled only if every open order, customer, and inventory item is in a state that can be saved.

Save Active:

Let's say my application has a tab control where I add many views. I've opened several orders, customers and inventory items, each with its own tab. Only one tab can be selected at a time. If I were to invoke the Save command, I would expect that only the selected order, customer, or inventory item would respond. In addition, I would like only the selected item to participate in the enablement of the Save command invoker(s). Selecting a tab for an item that is failing validation and therefore not saveable results in disabling the Save command invoker(s). Selecting a tab for an item that is in a saveable state results in the Save command invoker(s) being enabled.

The Save Active scenario may be solved using WPF RoutedCommands. However, as I've mentioned in a previous blog, we stayed away from RoutedCommands in favor of a more direct method of command invoker to handler routing. (One scenario that we support is the ability to have command handlers live in controllers, presenters, or presentation models. In the case of a controller providing a command handler, there may be no UI element that could provide a CommandBinding. Also, we may want to invoke the Save or SaveAll commands on items that does not necessarily have keyboard focus.)

Let's get back to Save Active. What we really need is to have container controls such as selectors communicate to us which of its child views is selected so that we can relay that information to the selected view's presentation model. The selected view's presentation model owns has handlers for the Save command. In the case where the selected view is actually a composite view, each of the child views would also need to receive the notification.

We discussed the name "ActiveAware" several times. We also considered names using "Selected" and other verbs. Finally we accepted that the initial act of selecting a view in a selector control (e.g. TabControl) allows us to know which of the selector's direct children is selected. After that, it made more sense to "Activate" rather than "Select" the child views/presenters/commands.