Dialogs in WP7

Mar 18, 2011 at 7:13 PM
Edited Mar 18, 2011 at 7:13 PM


I'm trying to do some "modal" dialog/page, and I need to get some result from this dialog (it's VM) to the previous page (it's VM). What is the recommended way in CM ? 

Thank your very much

Mar 19, 2011 at 8:52 AM

I usually provide a public property on the dialog VM to hold the result. The calling VM, which already has a reference to the dialog VM, could read the result on dialog closing.
To avoid dealing explicitly with lifecycle events (in order to know exactly when the dialog will be closed) I also suggest to open the dialog with a custom IResult and use Coroutines.

For example, using this custom IResult:

 public class ShowDialog : IResult
        readonly Type screenType;
        readonly string name;

        public IWindowManager WindowManager { get; set; }

        public ShowDialog(string name)
            this.name = name;

        public ShowDialog(Type screenType)
            this.screenType = screenType;

        public void Execute(ActionExecutionContext context)
            var screen = !string.IsNullOrEmpty(name)
                ? IoC.Get<object>(name)
                : IoC.GetInstance(screenType, null);

			Dialog = screen;
            var deactivated = screen as IDeactivate;
            if (deactivated == null)
			Completed(this, new ResultCompletionEventArgs());
		else {
			deactivated.Deactivated+=(o,e)=> {
				if (e.WasClosed) {
					Completed(this, new ResultCompletionEventArgs());

	public object Dialog {get; private set;}
        public event EventHandler<ResultCompletionEventArgs> Completed = delegate { };

        public static ShowDialog Of<T>()
            return new ShowDialog(typeof(T));

...you can write the following code:

public class SomeDialogViewModel {
	//this property is set within this class with the result of user interaction
	public string TheDialogResult {get;set;}

public class ParentViewModel {

	public IEnumerable<IResult> ShowSomeDialogAndGetResult() {
		var openDialog = ShowDialog.Of<SomeDialogViewModel>();
		yield return openDialog;
		var result = ((SomeDialogViewModel)openDialog.Dialog).TheDialogResult;
		//use result


Mar 19, 2011 at 8:41 PM

Ok, thank you.

but, what about WindowManager, I'm somehow able to use (or replace with something) it in WP7 ?

Mar 20, 2011 at 11:54 AM
Edited Mar 20, 2011 at 11:54 AM

Sorry, I always forget that WindowManager is not supported in WP7 :-)
In the linked thread there is a PopupResult that you can use to show a popup dialog.
It, however, misses at least one important feature: it should automatically close if the back button is pressed (to be compliant with WP7 marketplace requirements).

I'm starting to implement a WindowManager version for WP7 to better support this scenario; I'll post the code here as soon as I can.

Apr 1, 2011 at 8:34 PM
Edited Apr 1, 2011 at 9:06 PM

I finally pushed the WindowManager implemenentation for WP7 in the repository (changeset ff8f27cb3fb0).
It supports two methods, both accepting a ViewModel to activate and an (optional) context specifying the view to display: 

void ShowDialog(object rootModel, object context = null)

It shows the view associated with the VM into a dialog, reproducing the behavior of other WP7 system dialog windows.
In particular:

  • the client area is layed out on the upper part of the screen;
  • the underlying page is masked with a semi-transparent layer in order to prevent user interaction while the dialog is visible;
  • as soon as the underlying page orientation changes, the dialog is repositioned accordingly;
  • the dialog is automatically closed when the user presses the hardware "back" command (as specified in the Certification requirements #5.2.4.c);
  • the dialog is NOT restored after a Tombstoning.

Since the application bar (if any) cannot be overlayed, the WindowManager takes care of disabling it while the dialog is visible.

void ShowPopup(object rootModel, object context = null, IDictionary<string, object> settings = null);

It shows the view associated with the VM into a popup.
The setting parameter allows you to set the properties of the popup befere it is shown.
Please note that WindowManager doesn't add any behavior to native Popup.
In particular, no attempt is made to correct Popup positioning, which is always relative to the upper left side of the phone screen, regardless of the screen orientation and the visibility of the system tray.

Apr 1, 2011 at 10:08 PM

@marcoamendola, thank you very much...

Giving it a try. I've never been pleased with my own implementation.

Apr 2, 2011 at 12:38 AM


Definitely, your kung-fu is better than mine. Great contribution!

In your sample I've spotted RegisterWithPhoneService method. How/when you're using it?

Apr 2, 2011 at 3:38 AM
Edited Apr 2, 2011 at 11:22 AM

I never noticed it, to be honest :-) 

I borrowed the PhoneContainer implementation in the other Rob's WP7 sample (HelloWP7).
I guess RegisterWithPhoneService is used to register a singleton service in the container and preserve its state between application tombstoning.

Thanks for pointing out this hidden gem ;-)


Apr 22, 2011 at 2:11 PM

What if i want to show a control like the datepicker from the dialog window, then the control would get below the dialog window semitransparent mask? Is there any good way to solve this?

Apr 22, 2011 at 2:53 PM

Unfortunately, the team that created the date picker control did a poor job of it. They should not have implemented it as a page navigation. That breaks a lot of stuff in people's apps. As a result, there's no way to show an overlay with a datepicker that I can think of. You could implement your own datepicker control, but that's probably rather work-intensive. You might consider just using a page navigation instead of showing a modal. Sorry.

Apr 26, 2011 at 4:47 AM

I think the major reason the DatePicker was implemented using page navigation because of the way UI inside of a Popup doesn't perform terribly well.

Apr 26, 2011 at 8:02 AM
Edited Apr 26, 2011 at 8:03 AM

I agree that datepicker leaves very little flexibility, but I guess that it was intended to force devs to not break the WP7 UX idioms and design.
The dialog was designed mostly to show messages to the user, and it has not been tested in the scenario you reported; as far I know, devs are supposed to use a fresh page for every not trivial input dialog.
Even the simple input box in the WP7 dialog sample might be on the edge of "allowed" complexity.

That being said, integrating the existing DatePicker could be a little cumbersome.
The datepicker control forces a page navigation when a date is being selected; as a consequence, the dialog should be hidden before navigating to the picker page, then restored at the end (it does not participate in the navigation history). I'm not sure it'll work, though: I should have a closer look.

May 22, 2011 at 12:52 AM

I've managed to get the dialog to work with DatePicker too; now the dialog is hidden when the control navigates to the picker page and restored when navigating back.
I still think that a complex input form deserves a dedicated page on WP7, but now you can choose to use it anyway.

I'll commit the new stuff on the trunk as soon as possible.

May 22, 2011 at 10:27 AM

Committed the modification and updated the sample: 1bbfc0c904b4

Jul 29, 2011 at 3:43 PM

I tried using this ShowDialog implementation but ShowSomeDialogAndGetResult() is never executed. I tried it like this:

public void Edit()

      public IEnumerable<IResult> ShowSomeDialogAndGetResult()
         var openDialog = ShowDialog.Of<MyViewModel>();
         yield return openDialog;

         //use result

What could prevent the ShowSomeDialogAndGetResult() method to be executed? Do I have to invoke it in different way?

Jul 29, 2011 at 3:47 PM

Have you tried changing the Edit signature to the following one?

IEnumerable<IResult> Edit()

Jul 29, 2011 at 9:42 PM

Perhaps it could be useful to elaborate a bit BladeWise's advice (which is definitely correct).
Calling ShowSomeDialogAndGetResult coroutine just causes the creation of an IEnumerable<IResult> instance, which is immediatly discarded (since the return value of ShowSomeDialogAndGetResult is never used).
The coroutine is not executed unless it is directly invoked by an Action (for example with <Button cal:Message.Attach="ShowSomeDialogAndGetResult" />  ) or it is returned by another coroutine (as BladeWise suggested:   public IEnumerable<IResult>Edit() { return ShowSomeDialogAndGetResult(); } )
A third option (not so useful in this context but worth knowing) would be explictly requiring CM to start executing the coroutine:

public void Edit(){

Hope it helps.

Jul 30, 2011 at 2:40 AM

Thanks Marco, I wanted to write more, but I was busy and it was the best answer I could give in 10 seconds! :)

Jul 30, 2011 at 10:00 PM

Ok that's the solution. Thank you both for that great support.

Jun 21, 2013 at 4:41 PM
Edited Jun 24, 2013 at 11:00 AM

my first post at codeplex, so please excuse ;)

To Mr. Eisenberg: i love Caliburn.Micro!

But I got one small problem with the code mentioned from Marco Amendola. You wire up the "Completed"-Event just after "WindowManager.ShowDialog(screen);".
In case of an "DialogViewModel" that's implementing "IDeactivate", that's a little bit late, I think. Because the "Completed"-Event is fired immediatly after closing the dialog. So at first using of the dialog the event is not fired after closing.
So I decided to split up the if-statement like follows:
[Edit] After some research, I realise that there is a potential memory-leak, because the anonymous event-handler get's attached every time we call "Execute"! So I decided to store the event-handler localy and remove it after the dialog is closed:
        public void Execute(ActionExecutionContext context)
            var screen = !string.IsNullOrEmpty(_name)
                ? IoC.Get<object>(_name)
                : IoC.GetInstance(_screenType, null);

            Dialog = screen;

            EventHandler<DeactivationEventArgs> handler = (o, e) =>
                    if (e.WasClosed)
                        Completed(this, new ResultCompletionEventArgs());

            var deactivated = screen as IDeactivate;
            if (deactivated != null)
                deactivated.Deactivated += handler;


            if (deactivated != null)
                deactivated.Deactivated -= handler;
                Completed(this, new ResultCompletionEventArgs());
Hopefully, I didn't oversee something. Any investigation is very welcome!

Thanks for all your work!

Btw, please excuse my very bad english, but it's not my native language...