【问题标题】:Creating Flex components from XML从 XML 创建 Flex 组件
【发布时间】:2011-01-13 00:22:05
【问题描述】:

我有一个 XML,它有一个属性选项或组合框,解析我需要在我的 flex 中动态创建组件。

Viatropos 提供了一个很棒的代码,但我无法执行它...任何人都可以生成它...谢谢

【问题讨论】:

  • 你需要问一个问题...
  • 我想创建读取 XML 的组件

标签: xml apache-flex actionscript-3 dynamic


【解决方案1】:

您可以使用以下方式在 Flex 中动态创建组件:

样本数据

<?xml version="1.0" encoding="UTF-8"?>
<components type="array">
    <component type="mx.controls.ComboBox">
        <width>100</width>
        <height>100</height>
        <color isStyle="true">0xff0000</color>
        <prompt>Im a Combo Box!</prompt>
    </component>
    <component type="mx.controls.Button">
        <width>100</width>
        <height>100</height>
        <color isStyle="true">0xff0000</color>
        <label>Im a Button!</label>
    </component>
</components>

示例应用

<?xml version="1.0" encoding="utf-8"?>
<mx:Application
    xmlns:mx="http://www.adobe.com/2006/mxml"
    creationComplete="creationCompleteHandler()">

    <mx:Script>
        <![CDATA[

            import flash.display.DisplayObject;
            import mx.core.UIComponent;
            import mx.controls.ComboBox; ComboBox;

            protected function creationCompleteHandler():void
            {
                var components:Array = getComponentsFromXML(xml.component);
                var i:int = 0;
                var n:int = components.length;
                for (i; i < n; i++)
                {
                    panel.addChild(components[i] as DisplayObject);
                }
            }

            /**
             *  Parses an XML string, returns array of new components.
             */
            public function getComponentsFromXML(components:XMLList):Array
            {
                var result:Array = [];
                var child:Object;
                var component:UIComponent;
                var type:String;
                var clazz:Class;
                var i:int = 0;
                var n:int = components.length();
                for (i; i < n; i++)
                {
                    child = components[i];
                    type = child.@type;
                    try {
                        clazz = flash.utils.getDefinitionByName(type) as Class;
                    } catch (error:ReferenceError) {
                        traceImportError(type);
                    }

                    component = new clazz(); // dynamic

                    var properties:XMLList = child.elements();
                    var property:XML;
                    var name:String;
                    var value:Object;

                    // for each child node
                    for each (property in properties)
                    {
                        name = property.localName();
                        value = property.toString();
                        // create a more generic method to convert
                        // strings to numbers and whatnot
                        // this is a regular expression matching any digit
                        // check out rubular.com
                        if (/\d+/.test(value.toString()))
                            value = Number(value);

                        if (property.attribute("isStyle") == "true")
                            component.setStyle(name, value);
                        else
                            component[name] = value;
                    }
                    result.push(component);
                }
                return result;
            }

            protected function traceImportError(type:String):void
            {
                trace("Please include the class '" + type + "' in the swf.");
                var names:Array = type.split(".");
                var last:String = names[names.length - 1];
                trace("import " + type + "; " + last + ";");
            }

        ]]>
    </mx:Script>

    <!-- sample data -->
    <mx:XML id="xml" source="components.xml" />

    <!-- sample container -->
    <mx:Panel id="panel" width="100%" height="100%"/>

</mx:Application>

只要您为 XML 定义了结构,您就可以创建一个 XMLUtil 用于一般地处理 xml(例如,获取所有属性,或将字符串转换为正确的类型),以及一个采用 XML 文件的 ComponentManifest 类并将其转换为组件。

您还需要确保将 XML 中定义的所有类都导入到 swf 中,否则会抛出该错误。你可以这样做:

import mx.controls.ComboBox; ComboBox;

直接导入,没有第二个 ComboBox 将无法做到。

这应该可以帮助您入门,根据需要填写!

如果您想要更好/更高级的 xml 值解析,请查看 RubularRegular Expressions 混在一起:)。

【讨论】:

  • 你能提供我完整的...代码我遇到了一些错误
  • @viatropos:谢谢你的回答,我今天刚学了点新东西 :)
【解决方案2】:

这是@viatropos 解决方案的修改版本:

样本数据:

<?xml version="1.0" encoding="UTF-8"?>
<components type="array">
    <component type="mx.controls::ComboBox">
        <width>100</width>
        <height>100</height>
        <color isStyle="true">"0xff0000"</location>
        <label>"Im a Combo Box!"</label>
    </component>
    <component type="mx.controls::Button">
        <width>100</width>
        <height>100</height>
        <color isStyle="true">"0xff0000"</location>
        <label>"Im a Button!"</label>
    </component>
</components>

这里显然有一个错误,用于结束标签。

我还在所有字符串值周围添加了引号,以便于识别它们。

示例(伪)方法: createComponentsFromXML(xml.components)

public function createComponentsFromXML(components:XMLList):void
{
    var child:Object;
    var component:UIComponent;
    var i:int = 0;
    var n:int = components.length();
    for (i; i < n; i++)
    {
        child = components[i];
        var clazz:Class = flash.utils.getDefinitionByName(child.@type);
        component = new clazz(); // dynamic
        var property:Object;
        var value:Object;
        var useIntVal:Boolean;
        var intVal:int;
        // for each child node
        for (property in child.children())
        {
            useIntVal = false;
            value = property.toString();
            if(!(value.substr(1, 2) == '"' AND value.substr(-1, value.length()) == '"')) {
                useIntVal = true;
                intVal = parseInt(value);
            }
            // button["width"] = 100;
            if (property.attribute("isStyle") == "true")
                if(useIntVal) {
                    component.setStyle(property.localName(), intVal);
                } else {
                    component.setStyle(property.localName(), value);
                }
            else {
                if(useIntVal) {
                    component[property.localName()] = intVal;
                } else {
                    component[property.localName()] = value;
                }
            }
        }
    }
}

我实现了到 int 的转换,确保我检查了属性应该是字符串还是 int。

PS:我现在没有安装 Flex,所以你可能会发现一些需要纠正的错误。

在这种情况下,您可能希望您的 XML 像这样:

<?xml version="1.0" encoding="UTF-8"?>
<components type="array">
    <component type="mx.controls::ComboBox">
        <properties>
            <width>100</width>
            <height>100</height>
            <color isStyle="true">"0xff0000"</location>
            <label>"Im a Combo Box!"</label>
        </properties>
    </component>
    <component type="mx.controls::Button">
        <properties>
            <width>100</width>
            <height>100</height>
            <color isStyle="true">"0xff0000"</location>
            <label>"Im a Button!"</label>
        </properties>
        <children>
            <!--other children here-->
        </children>
    </component>
</components>

因为我怀疑你可以在手风琴中使用一层嵌套做很多事情。

我将把实现该功能的工作留给你。

【讨论】:

  • 我们能否在 Accordian 中创建组件...取决于 XML
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-01
  • 2012-04-29
  • 2011-03-12
相关资源
最近更新 更多