DialogResult from Modal dialog

Topics: CAB & Smart Client Software Factory
Sep 29, 2006 at 5:22 AM
originally posted by: gcole

I'm creating a modal dialog in the WorkItem ModalWindows workspace. When the dialog closes, I need to take different action based on whether the OK or Cancel button was clicked. Anybody know how to determine how the modal view was closed?

thanks
Jul 18, 2007 at 9:53 PM
I'd like to know how other have handled this as well. I can think of a couple of different ways to solve the problem but none of them seem all that great.

The cleanest way I can think of is to add a DialogResult property to the View interface and store the DialogResult from the presenter into a member var on the View. This seems like it would break the design intentions of CAB (working directly with the view).

We don't have access to the presenter from the calling code so that isn't a good option.

You could uses events, but that is REALLY ugly.
Anyone have an elegant solution? Please share.
Jul 19, 2007 at 12:13 AM
I'm not sure if that of any help to you but I think Chris Holmes has an article on how to display a message box and a dialog box. Maybe he's tackling your problem there.

T.
Jul 19, 2007 at 3:28 AM
Edited Jul 19, 2007 at 3:30 AM
I would have thought you should use the WorkItem.State to store whatever you're after. There has to be some parent WorkItem to whatever your're doing, and all of your SmartParts have access to it (via dependency injection) so why not store the result of the OK/Cancel button in there and access it from wherever you like (eg another SmartPart) and take action?
Jul 19, 2007 at 4:27 AM
I've got a post here: http://www.chrisholmesonline.com/2007/03/07/messagebox-dialogbox-in-cab-updated/

To be honest though, where I work we've stopped using WindowWorkspace for Dialogs and MessageBoxes. Instead, we make that part of the View definition, and leave it to the concrete View to implement the specific details.

For instance, imagine a View that has a list of Departments that an Employee belongs to (sounds kind of silly, doesn't it? Yet where I work, people can actually have portions of their pay budgeted to multiple departments) Anyway, there's a button on the view to AddDepartment.

A Command or Event or direct method call to the Presenter might be triggered by that button click. The presenter can then do:

View.GetDepartmentToAddFromUser()

Inside the View we'll implement the call to open that Dialog, provide the user with any pre-filled drop down lists, and then the View code will manage the very simple (and difficult to screw up) code: DialogResult == Something...

The View then makes a call to the Presenter based on the DialogResult, like:

_presenter.AddDepartment(departmentID);

Or if the user canceled the action (DialogResult.Cancel) then nothing.

In this way, the generic interface definition to the View is very descriptive (GetDepartmentToAddFromUser) bu the specific implementation detail is up to the view. I can use a Dialog if it wants to, it could use a different method as well. A different view implementing the same interface isn't beholden to show a dialog; it could use a random dice selection for all we care.

We've found this gives us a couple advantages when dealing with DialogBoxes:

(A) We're able to deal with Dialogs and MessageBoxes in a way that is native to WindowsForms without breaking CAB
(B) The DialogBoxes and MessageBoxes don't popup during unit testing because they are implementation details on the concrete View. Mock views or Stub Views won't have the Dialog component, just a very simple interaction via a call to GetDepartmentToAddFromUser(). Which, when you read the unit tests, makes perfect sense, and we don't care about the implementation details - just that the user provides the Department.

I should probably blog this and update the old WindowWorkspace posts (or...what's the term... Deprecate them hehe)

On vacation for a few days - in case anyone asks!

-Chris
Jul 19, 2007 at 10:14 AM
Hi Chris,

Quick questions:

1. When you say you've stopped using WindowWorkspace for Dialogs and MessageBoxes, do you mean using it via WindowWorkspace.Modal?
2. When you say "Inside the View we'll implement the call to open that Dialog", what do you mean?

You recently help me with another post. Is this the right method or is this something completely different from what I had?

Thanks.

Thierry
Jul 19, 2007 at 2:44 PM

tfierens wrote:
Hi Chris,

Quick questions:

1. When you say you've stopped using WindowWorkspace for Dialogs and MessageBoxes, do you mean using it via WindowWorkspace.Modal?
2. When you say "Inside the View we'll implement the call to open that Dialog", what do you mean?

You recently help me with another post. Is this the right method or is this something completely different from what I had?

Thanks.

Thierry


I was thinking about this last night after I wrote it. We do still use the WindowWorkspace in one place in a modal situation, so we haven't abandon it completely.

As for question 2, we'll do something like this:

The View will contain a method called something like GetSomeDataFromUser();

The implementation of that method inside the view will look like this:

public void GetSomeDataFromUser(DataForADropDownList listData)
{
 
   SomeDataDialog dialog = new SomeDataDialog();
   dialog.StartPosition = FormStartPosition.CenterParent;
   dialog.DataForSomeDropDownList = listData;
   
   if(dialog.ShowDialog() == DialogResult.Ok)
   {
      _presenter.SaveData(dialog.DataA, dialog.DataB, dialog.DataC);
   }
}

So what we're asking the view is to get some data from the user, and the fact that we're using a dialog box to accomplish it just becomes an implementation detail of the view.
Feb 4, 2008 at 9:42 PM
Is your SomeDataDialog a class that inherits directly from System.Windows.Forms.Form?
Aug 14, 2008 at 8:00 AM
Edited Aug 14, 2008 at 8:12 AM
I'm not sure if it helps, but we have subclassed the SmartClient WindowWorkspace (ModalDialogWorkspace) and added a DialogResult property to it (the workspace). Like you can access the 'Pages' property of the TabWorkspace to irerate through the tabpages, my ModalDialogWorkspace control has a DialogResult property. I have also subclasses the SmartClient WindowSmartPartInfo class and added a property DialogButtons that uses a ModalDialogButtons enumeration which 'inherits' from MessageBoxButtons. The buttons itself are placed on a FlowLayoutPanel (right-to-left direction) which is also exposed as an UIExtensionSite so views can add custom buttons to it. The 'Show' method on the ModalDialogWorkspace is blocking, but it's still a void (otherwise it would not match the IWorkspace.Show method).


ModalDialogSmartPartInfo info = new ModalDialogSmartPartInfo();
info.DialogButtons = ModalDialogButtons.OKCancel;

//get dialog workspace
ModalDialogWorkspace dialog = WorkItem.Workspaces[WorkspaceNames.ModalDialog] as ModalDialogWorkspace;
if (dialog == null)
  throw new WorkspaceMissingException("ModalDialogWorkspace");


IDialogView view = WorkItem.SmartParts.AddNew<LoginDialog>();
dialog.Show(view);

//we won't get here till a value on the DialogResult property is (setter calls Close())
if (dialog.DialogResult != DialogResult.OK)
   return; //exits the application

ControlledWorkItem<ApplicationController> ctl= WorkItem.WorkItems.AddNew<ControlledWorkItem<ApplicationController>>();
ctl.Controller.Run();


I will see if I somewhere can post the full ModalDialogWorkspace code.