tags:

views:

5245

answers:

3

I've done a lot of C# programming with both Winforms and WPF. I'm working on a Flex/Air app now for cross platform support. But this is my first flex project, so I'm learning as I go.

I've got a window that I want to popup, that the user will fill out a form, then hit OK or CANCEL. I set it up the same way I would've in C#, but it doesn't work, and I can't really see a way to make it do what I want.

EDIT: So I'm trying events now, the events just don't seem to be handled...

EDIT again: Oh, It's because the popup manager seems to create a new instance of the Form object, rather than using the one I created already.

so in the showWindow method, I put in this code rather than the popup manager:

parent.addChild(this);

then I remove it when I close it. The only problem is, it doesn't disable the rest of the parent like the popup manager does. Any suggestions on that?

PARENT:

private function btnAdd_Clicked():void
{      
        var form:Form = new Form();
        form.addEventListener(CloseEvent.CLOSE, onFormClosed, false, 0, true);

        recipeForm.showWindow(this);
}

private function onFormClosed(e:CloseEvent):void
{
    //none of these Alerts are ever shown. I also tried breakpoints in debug to try an follow the code, with no luck
    Alert.show("Closed");
    if(e.detail == Alert.OK)
    {
        Alert.show("OK");
    }
    else if(e.detail == Alert.CANCEL)
    {
        Alert.show("Cancel");
    }
}

CHILD:

private function btnCancel_Clicked():void
{
    okClicked = false;
    closeWindow();
}

public function closeWindow():void
{
    var e:CloseEvent = new CloseEvent(CloseEvent.CLOSE);
    e.detail = okClicked ? Alert.OK : Alert.CANCEL;
    dispatchEvent(e);
    PopUpManager.removePopUp(this);
}

public function showWindow(parent:WindowedApplication):void
{
    var window:IFlexDisplayObject = PopUpManager.createPopUp(parent, RecipeForm, true);
    PopUpManager.centerPopUp(window);
}
+2  A: 

You can do this at least two different ways:

FIRST WAY: Using events

Let your Form class dispatch an event when either of the buttons is clicked. After Form is instantiated from the parent view, add an eventListener for the event(s) it's known to dispatch. When the Form dispatches the event, the eventListener will be invoked. You can even reuse Flex's CloseEvent and set the "detail" property to either Alert.OK or Alert.CANCEL before dispatching it.

In Form:

var e:CloseEvent = new CloseEvent(CloseEvent.CLOSE);
e.detail = okClicked ? Alert.OK : Alert.CANCEL;
dispatchEvent(e);

In parent:

var f:Form = new Form();
f.addEventListener(CloseEvent.CLOSE, onClose, false, 0, true);
...
private function onClose(e:CloseEvent):void
{
    if (e.detail == Alert.OK)
        // do something
    else if (e.detail == Alert.CANCEL)
        // do something else
}

SECOND WAY: Using callbacks

Add a public var of type "Function" to your Form class and supply a callback function from the parent. This does basically the same thing as #1 except with little less abstraction / indirection.

I would recommend #1 since the event model in Flex is pretty well-conceived and more flexible than the callback.

cliff.meyers
This seems like it should work, but the event just doesn't seem to be handled...child:public function closeWindow():void{ var e:CloseEvent = new CloseEvent(CloseEvent.CLOSE); e.detail = okClicked ? Alert.OK : Alert.CANCEL; dispatchEvent(e); PopUpManager.removePopUp(this);}parent:private function btnAddRecipe_Clicked():void{ var recipeForm:RecipeForm = new RecipeForm(); recipeForm.addEventListener(CloseEvent.CLOSE, onRecipeFormClosed, false, 0, true); recipeForm.showWindow(this);}private function onRecipeFormClosed(e:CloseEvent):void{ //never gets gets here... :/}
Joel
oh, comments don't allow line breaks... oopps... I'll edit it into my original post.
Joel
Well it looks like showWindow() is returning a fresh instance of your RecipeForm class. You want to attach the event listener to that class. You need to be sure that the object you dispatch the event from is the same one that has the listener registered to it.
cliff.meyers
+1  A: 

In Form:

var e:CloseEvent = new CloseEvent(CloseEvent.CLOSE); e.detail = okClicked ? Alert.OK : Alert.CANCEL; dispatchEvent(e);

In parent:

var f:Form = new Form(); f.addEventListener(CloseEvent.CLOSE, onClose, false, 0, true); ... private function onClose(e:CloseEvent):void { if (e.detail == Alert.OK) // do something else if (e.detail == Alert.CANCEL) // do something else }

A: 

Not sure if this is still an open issue. I ran into this very same problem and I think I figured out what is wrong. At least I did for my problem.

I implemented things exactly as you did. I also have the close attribute set to closeWindow (I'm using a TitleWindow for my dialog).

So when the window is closed via the X at the top, it will call closeWindow, also if you click on the Cancel button, it will also call closeWindow. The problem for me was that clicking cancel, dispatches a CloseEvent which seems to be caught by a Listener which calls closeWindow again (possibly via the close attribute which probably creates its own internal listener). I'm not sure if its an infinite loop but Flex does not like this.

My solution was to create two functions, one for the X close window to call and one for the Cancel button to dispatch a CloseEvent of its own. This seemed to work for me. Hope it helps you.

Ryan K