0

I'm trying to figure out the right approach for "Code behind" using flash builder for a mobile app:

  1. I'm creating a flex mobile AIR project (Based on the "Tabbed view" template)
  2. setting my UI in design mode
  3. now I want all the logic to be in a separate class that will change the UI look accordingly

Sounds easy, however I can't really get the approach for doing it, any help is appreciated :)

Update:

main app:

<?xml version="1.0" encoding="utf-8"?>
<s:TabbedViewNavigatorApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
                                  xmlns:s="library://ns.adobe.com/flex/spark" applicationDPI="160">
    <s:ViewNavigator label="a" width="100%" height="100%" firstView="views.aView"/>
    <s:ViewNavigator label="b" width="100%" height="100%" firstView="views.bView"/>
    <fx:Declarations>
        <!-- Place non-visual elements (e.g., services, value objects) here -->
    </fx:Declarations>
</s:TabbedViewNavigatorApplication>

view A:

<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009" 
        xmlns:s="library://ns.adobe.com/flex/spark" title="a">
    <fx:Declarations>
        <!-- Place non-visual elements (e.g., services, value objects) here -->
    </fx:Declarations>
    <s:Label id="txt" x="280" y="139" text="Label"/>
</s:View>

So now I want MyClass to change txt textField according to my logic, what is the right approach?

Shlomi Schwartz
  • 8,693
  • 29
  • 109
  • 186
  • I understand that you want to separate out your AS3 code and MXML code, is that correct? You won't be able to do this by using Design Mode. – JeffryHouser May 31 '12 at 14:47
  • I think you may be confused about using code behind... or I'm confused about what you're trying to do one of the two :). Normally you would pass data into a view and you could set the view up to respond appropriately to the data assigned to it. This doesn't require code behind. If you have shared logic between the views that you want to reference from each you could create a common base class for both views (in a sense "code-behind") you could also use static methods on a separate "utility" class. There's many possible approaches. – shaunhusain May 31 '12 at 17:24

3 Answers3

0

All you do is make an AS file that has the same base class as whatever your MXML object was initially set up as, for example if it's a VGroup make MyBaseClass extends VGroup, then change the VGroup to MyBaseClass.

Example

[Main.mxml]

<main:MainBase 
   xmlns:main="*"
   ...>
</main:MainBase>

[MainBase.as]

public class MainBase extends Application
shaunhusain
  • 19,630
  • 4
  • 38
  • 51
  • Also I recommend not using the design mode, it's fine for throwing things together in a rough way but if you don't understand the underlying layout it's going to be difficult to do everything in design mode and get it to properly scale, that is unless you're not concerned with scaling. – shaunhusain May 31 '12 at 14:50
  • Thanks for the reply, but does it mean that I will have to declare all my MXML elements inside my MainBase in order to get a referance? – Shlomi Schwartz May 31 '12 at 14:53
  • 1
    Yup, I'm not the biggest fan of this method but it does work. – shaunhusain May 31 '12 at 14:54
  • 1
    Personally I'm okay with having a script block in my MXML rather than dealing with declaring all the parts I'm concerned with accessing in "code behind". – shaunhusain May 31 '12 at 14:55
  • It's understandable in some cases, in these cases this is the way to go, and like you said you just have to declare whatever UIComponents you need a handle on in the base class. Like if there was a button I need a handle on it Main.mxml called submitButton then in MainBase you declare public var submitButton:Button; and just don't create it there. You're safe to assume after creation complete the sub class will have created the button and you can do your logic as necessary. – shaunhusain May 31 '12 at 17:18
  • Make sure you declare it as bindable if you ever think you might need it to be. Declaring variables in AS and not making them bindable makes them not bindable, even though we expect objects created in MXML to be bindable. – Amy Blankenship Jun 02 '12 at 12:53
0

Think of your Code Behind as a base class (or an Abstract Class). In an Abstract Class, it is really common for the actual implementation of methods or the "real objects" behind properties to be left to the extending class(es) to supply.

This is exactly like what you do when you set a base class in Flash to your custom Class, but the actual member objects (buttons, etc.) are provided on the stage of the MovieClip whose library instance is linked to your clip.

For more on code behind, check out my blog post here. If you'd like to check out the code for the template component described there, look here. Though template components are less useful in the Spark world (IMO).

Amy Blankenship
  • 6,485
  • 2
  • 22
  • 45
0

An elegant way would be implementing IMXMLObject. When implementing this interface, the IMXMLObject#initialize method will take the component (named document of type Object) and an optional id (of type String) as arguments and u can easily implement this pattern. The big advantage is, that you use composition over inheritance and when using interfaces, you can use it as some sort of type save mix-in as view behavior:

    package net.icodeapp.examples.views
    {
      import flash.events.MouseEvent;

      import mx.core.IMXMLObject;
      import mx.events.FlexEvent;

      public class ViewBaseModel implements IMXMLObject
      {
        //-------------------------------------------------------------------------
        //
        //          Properties
        //
        //-------------------------------------------------------------------------

        private var _id:String;

        private var _viewBase:ViewBase;

        protected function set viewBase(value:ViewBase):void
        {
          _viewBase = value;

          if (!_viewBase)
            throw new ArgumentError('View must be instance of ViewBase');

          if (!_viewBase.initialized)
            _viewBase.addEventListener(FlexEvent.CREATION_COMPLETE, viewBase_creationCompleteHandler, false, 0, true);
          else
            viewCreationCompleted();
        }

        //-------------------------------------------------------------------------
        //
        //          Constructor
        //
        //-------------------------------------------------------------------------

        public function ViewBaseModel()
        {
        }

        //-------------------------------------------------------------------------
        //
        //          Methods
        //
        //-------------------------------------------------------------------------

        public function initialized(document:Object, id:String):void
        {
          viewBase = document as ViewBase;
          _id = id;
        }

        private function viewCreationCompleted():void
        {
          _viewBase.addEventListener(MouseEvent.CLICK, viewBase_clickHandler);
        }

        //-------------------------------------------------------------------------
        //
        //          Event Handler
        //
        //-------------------------------------------------------------------------

        private function viewBase_creationCompleteHandler(event:FlexEvent):void
        {
          viewCreationCompleted();
        }

        private function viewBase_clickHandler(event:MouseEvent):void
        {
          // todo: do some action
        }
      }
    }

The model is initialized and references are set by the framework. When taking a peek at the generated ActionScript code you'll see, that IMXMLObject#initialize it called in the constructor after the model is instantiated.

    <?xml version="1.0"?>
    <s:Group xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"
                 xmlns:views="net.icodeapp.examples.views.*">
      <fx:Declarations>
        <views:ViewBaseModel/>
      </fx:Declarations>
    </s:Group>

The model would receive by events by the view and can call methods on it.

Florian Salihovic
  • 3,921
  • 2
  • 19
  • 26