Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF and Prism View Overlay

I need some help with overlaying views using the prism framework.Its a little more complexed than that so let me explain.I could be over-thinking this as well :D

i have shell (wpf window) and i have 2 views(A & B - both usercontrols) in a module. when the shell loads it loads view A. On view A i have a button to "popup" view B for some user input. so naturally i would think to some sort of modal window/control, maybe even a popup. however the problem i face with the popup is that when i move the shell the popup remains fixed and it doesnt block events in view A. I've tried disabling view A to stop events being fired and i've also tried to use a to get the view B move with the shell. Only the canvas works but i now need a way to block it tho'. Is there anyway i can overlay a view on top of another view with prism? or how does everyone else create modal popups with prism & wpf? any advise or pointers would be greatly appreciated.

like image 638
Zaheer Avatar asked Mar 19 '10 13:03

Zaheer


2 Answers

If you want to use embedded dialogs without an extra window, you can use Prism's RegionManager to achieve the outlined behavior. The trick is to put the PopUp region parallel to your main region in the visual tree:

<Grid>
   <ContentControl cal:RegionManager.RegionName="MainRegion" IsEnabled={Binding IsNoPopUpActive} />
   <ContentControl cal:RegionManager.RegionName="PopUpRegion"/>
</Grid>

Now use the RegionManager to put view "A" into the "MainRegion". Create a controller class similar to IPopUpDialogController. It should be responsible for putting your view "B" (or any other PopUpView in your application) into the "PopUpRegion" on demand. Addtionally, it should control a flag that signal the underlying "MainRegion" to be enabled or disabled. This way a user won't be able to play with the controls in your view "A" until the pop up is closed.

This can even be done in a modal fashion by using ComponentDispatcher.PushModal() before pushing a frame onto the Dispatcher. However, I would recommend avoid modal dialogs.


Update: As requested in a comment, the IsNoPopUpActive could be implemented in the backing view model. There you could link it to RegionManager's View collection for the popup region:

public bool IsNoPopUpActive 
{ 
    get { return _regionManager.Regions["PopUpRegion"].Views.Count() == 0; }
}

Remember to trigger a PropertyChanged event as soon as you modify the views collection (add/remove a popup).

Just for your information: nowadays I avoid disabling the controls in the background and instead insert a transparent panel. This avoids clicking on background controls. However, this does not handle keyboard input (tab-ing to controls). To fix the keyboard input you need to make sure that the keyboard focus is trapped in the popup (MSDN on WPF Focus concepts).

Adding the following focus attributes to the popup region should do the trick:

KeyboardNavigation.DirectionalNavigation="None"
KeyboardNavigation.ControlTabNavigation="None"
KeyboardNavigation.TabNavigation="Cycle"
KeyboardNavigation.TabIndex="-1"
like image 117
olli-MSFT Avatar answered Oct 19 '22 02:10

olli-MSFT


If you are using WPF + MVVM with Prism you can take a look at this Message View overlay controller. The nice part about this approach is you can write unit tests on you view model using a mock overlay controller and have the mock controller return the result that the user would choose in the overlay.

You can find it here: http://presentationlayer.wordpress.com/2011/05/24/wpf-overlay-message-view-controller/

Hope this helps

like image 38
droidalmatter Avatar answered Oct 19 '22 01:10

droidalmatter