This project has moved. For the latest updates, please go here.

TransitioningContentControl and Jounce Region-based Navigation

Jan 13, 2011 at 5:06 PM
Edited Jan 13, 2011 at 5:19 PM

Hi Jeremy,

while reading your latest addition to the Jounce documentation - VisualStateAggregator and its application to VisualState animations - I stumbled across an animation scenario that is loosely connected to your VisualStateAggregator examples but works on the Region container level.

When you used Region-based navigation in Jounce with a ContentControl as the Region's underlying container, navigation between different Views is instantaneous meaning you get a hard switch from the previous View to the new View displayed in the Region. Replacing the ContentControl with a TransitioningContentControl from the Silverlight Toolkit allows you to augment navigation with a smooth transition effect - such as the new View sliding in from the right while the previous View slides out to the left. All it takes for this to work is a new TransitioningContentRegionAdapter, which is basically dead easy to implement.

Enter the scope of a Wizard-type navigation application where you can move forward or backward to some previous content. Using the TransitioningContentControl it is really easy to provide visually appealing effects for going forward (slide right->left) and going back (slide left->right) but unfortunately the present navigation infrastructure does not provide any context information with the ViewNavigationArgs that could be used by the TransitioningContentRegionAdapter to distinguish between forward and backward navigation (or any other navigation modes for that matter).

This scenario differs from your VisualStateAggregator example in that the set of Region content Views can be a set of entirely decoupled (possibly dynamically composed) entites that don't know about each other or their position in the Wizard navigation sequence.

Do you see any way of implementing the above scenario within the current capabilities of the Jounce framework, or would you otherwise consider adding a context property (e.g. NavigationMode) to the ViewNavigationArgs class so that a RegionAdapter can trigger different navigation behaviours?

Cheers,
DrJ

Coordinator
Jan 14, 2011 at 2:05 PM

I'll be posting an example shortly. The solution I've been using is straightforward:

Instead of a ContentControl, I use an ItemsControl and change the underlying panel to a Grid. Then the visual state aggregator can managing the show/hide and transitions and hook into the click trigger from navigation. Navigation doesn't even have to worry about them. I'll get the sample together and post over the next week or so.

Coordinator
Jan 14, 2011 at 2:06 PM

PS this would require a knowledge of the transition between one page and another, as opposed to the more generic one. The only hesitation I'd have is I'd be glad to publish a separate adapter for the control but wouldn't want a Toolkit dependency in the core - is great information for general guidance however.

Jan 14, 2011 at 3:36 PM
jeremylikness wrote:

PS this would require a knowledge of the transition between one page and another, as opposed to the more generic one. The only hesitation I'd have is I'd be glad to publish a separate adapter for the control but wouldn't want a Toolkit dependency in the core - is great information for general guidance however.

Actually the "more generic" approach is exactly what I'm after. For my scenario I'd rather not be forced to stick all the required Views into an ItemsControl because - like I wrote above - they may be dynamically composed and some steps might be skipped based on user choice. I'd like to stick with the "one content at a time" approach of the ContentControl region - just with a bit of transition animation added to it.

Regarding your second comment - I'm right with you in not wanting to introduce a Toolkit dependency into Jounce. The way I see it is that all that is required to make the "generic" approach work is an extension of the ViewNavigationArgs class with either a string property (e.g. "NavigationMode") or an even more general object-typed property (e.g. "NavigationContext") and a TransitioningContentAdapter. The adapter could be kept out of the general Jounce distribution to avoid the Toolkit dependency.

While this is a rather specific request I wouldn't be surprised if there were some other benefits to be gained from having a bit more context in the ViewNavigationArgs than just the pure next step name.

 

Regards,
DrJ

Coordinator
Jan 14, 2011 at 3:55 PM

Just to be clear, there is no reason you would have to stick them all in an items control. That is just the region container. They technically end up in a grid, and the navigation rules still follow - page 3 won't even exist until it is requested the first time, so that's not an issue at all.

I do agree on your enhancement idea for the navigation args and will look into that.

Jan 14, 2011 at 9:46 PM
Edited Jan 14, 2011 at 9:47 PM

You're certainly right - looks like I got sidetracked there.

But still - isn't the ItemsControl Region meant for several content items being displayed simultaneously? The Wizard navigation scenario I mentioned above would require hiding all but one of those at any single moment in time, wouldn't it? The ItemsContainer adapter could infer the requested navigation direction from the relative positions of the current and the requested view in the collection - true - but it still strikes me as kind of strange to use a collection-bound ItemsControlAdapter for this purpose.

Coordinator
Jan 15, 2011 at 10:14 PM

Take a look at the latest source drop, at VSMAggregator in the quick starts. This is the concept.

ControlControl = one view, ItemsControl = multiple. However, in Jounce, the views by default live on, regardless of whether or not they are in the visual tree. So ItemsControl might have multiple views but they don't have to be shown. When they are collapsed, the hit is minimal as they are no longer in the visual tree.

The transitioning content control is clever but to me adds a bit of overhead with the dep properties and hooks, etc, i'd rather just stack the views directly and allow VSM to manipulate them.

That's just a preference.

Jan 17, 2011 at 8:22 AM
Edited Jan 17, 2011 at 8:25 AM

VSMAggregator is obviously a very powerful and elegant instrument for controlling the display of Views with individually defined Visual States and transisions. The example from your latest source drop works perfectly in this respect. What I'm still missing is a way to handle RegionNavigation and VisualState transitions in an integrated and generic fashion without explicit knowledge of the Views involved.

Let me illustrate my scenario in some more detail. I have a bunch of Views (representing the steps of process wizards) - on the order of 50 altogether, spread across 10 different wizards. The application is designed to be extensible with additional wizards loaded through Jounce's excellent DeploymentCatalog infrastructure. In this context, it is undesirable to have individual transition effects designed inside the wizard steps due to both the sheer number of steps and the aim of keeping a consistent appearance across all of the wizards. I would therefore greatly prefer to be able to attach a transitioning behavior to the containing Region (ContentControl-based in my case) from the outside instead of leaving the choice to the individual Views.

Furthermore, the choice of the next navigation step is determined according to some involved business logic and cannot be statically embedded inside the Views directly as named VisualStateAggregatorTriggers ("NavigateRed" in your example). The only thing that would work would be something like  

<Views:VisualStateAggregatorTrigger EventName="NavigateForward"/> and <Views:VisualStateAggregatorTrigger EventName="NavigateBack"/>

but how would you go about disambiguating between the many Views containing a  

<Views:VisualStateSubscriptionBehavior EventName="NavigateForward" StateName="ShowState" UseTransitions="True"/> ?

Again, I totally agree with your reasoning against introducing a dependency on the Silverlight Toolkit into Jounce. I'd be happy to include a TransitioningContentControl-RegionAdapter as an individual component in my project. All I'm missing is a way to transport a string-typed tag from the initiator of the ViewNavigation message to the RegionAdapter so that the RegionAdapter can orchestrate the transitions on its content for the cases of "forward" or "backward" navigation directions.

Coordinator
Jan 17, 2011 at 11:07 AM

So it sounds like in this scenario, just thinking out loud, you would want to use some of the extra metadata tags on the view to categorize and order the views. Then you'd need a view controller that can basically query the metadata. Something has to drive that I'm in "wizard a" for example so the controller would track that (perhaps by inspecting the category on the view). Then the controller could keep track of where in the view stack you are. Instead of navigation trigger/VSM etc you would have your own behavior or command and when it's fired, it would delegate authority for navigation to the controller. The controller would look at forward/backwards etc and inspect the stack of views and raise the navigation event. For VSM, you would use the activate / decative methods on the VM to fire standard states (i.e. if you are going to participate in transitions, this is the show state, this is the hide state, etc).

Remember too that navigation is an event. So the controller can raise navigation and the region adapter can listen to navigation and handle the string manipulations (it already listens). Not sure if that makes sense but sounds like more of what you are asking about.

Jan 17, 2011 at 2:12 PM
Edited Jan 17, 2011 at 2:21 PM

Yes, precisely, all of the above. I didn't want to complicate matters by describing the architecture of my application in its entirety, but you nailed it down quite well.

What I'm using is an explicit NavigationService implementation (similar to the System.Windows.Navigation.NavigationService) that keeps a journal and encapsulates some of the forward/backward navigation mechanics while leaving the ultimate routing decisions (is there a next step, what is the next step based on data gathered in the current step, what if I go back and change data in the previous step, etc.) to application logic (a set of controllers associated with the diverse wizards). The controllers collect their associated wizard steps by MEF-composing Views of the appropriate categories. The NavigationService drives Jounce Region-based navigation by publishing ViewNavigation events via the EventAggregator and the views get inserted into the intended Regions via the ExportViewToRegion mechanism.

All of this works beautifully so far and I'm really happy with the smooth integration of several otherwise complicated mechanisms that Jounce offers under the hood. Except for a couple of minor extensions of course ;-) that I'd wish for in an 1.0 release of Jounce.

Now what I'm after is kind of the icing on the cake of Region navigation - namely integral support for separate forward/backward navigation animations.

jeremylikness wrote:

Remember too that navigation is an event. So the controller can raise navigation and the region adapter can listen to navigation and handle the string manipulations (it already listens). Not sure if that makes sense but sounds like more of what you are asking about.

If I understand correctly you suggest encoding the navigation mode within the navigation strings such as:

eventAggregator.Publish(new ViewNavigationArgs(string.Format("ViewType='{0}' Mode='{1}'", journal.CurrentEntry.Step, "forward")));

Well, this would certainly work but it looks kind of wrong to my eyes. String mangling is a relic from another time and and I'd only use it today as a last resort.

I'd much rather

eventAggregator.Publish(new ViewNavigationArgs(journal.CurrentEntry.Step) { Tag = "forward" });

or even

eventAggregator.Publish(new ViewNavigationArgs(journal.CurrentEntry.Step) { Mode = "forward" });