3

我正在尝试将 FormItem 用作 DataGroup 中的 ItemRenderer - 目的是基于 XMLlist 作为数据提供者动态创建表单。第一部分是成功的,因为表单项已成功呈现,但是我的问题是,尽管在 DataGroup 中使用了 FormLayout,但我的 FormItem 标签没有相互对齐。

<?xml version="1.0" encoding="utf-8"?>
<s:Application 
xmlns:fx="http://ns.adobe.com/mxml/2009" 
xmlns:s="library://ns.adobe.com/flex/spark" 
xmlns:mx="library://ns.adobe.com/flex/mx"
minWidth="955" minHeight="600"
>
<fx:Declarations>
    <fx:XMLList id="_formModel" >
            <control description="Weeks 1 Form Item"  id="087B4626-B95E-731F-ACC7-80ED7373E083" label="One" />
            <control description="Weeks 2 Form Item"  id="AC546361-D9C5-E9F3-5F90-80EFA52EF54D" label="Second"  />
            <control description="Weeks 3 Form Item"  id="9EE2AAA4-B9C3-68C0-D9B5-80F0374F940E" label="Three" />
            <control description="Weeks 4 Form Item"  id="3CCEABD6-12F9-E511-0C77-80F0A86902D5" label="The Fourth"  />      
    </fx:XMLList> 
    <s:XMLListCollection id="_controls" source="{_formModel}"/>
</fx:Declarations>

<s:Scroller width="100%" height="100%">
    <s:DataGroup width="100%" height="100%" dataProvider="{_controls}"  >
        <s:layout>
            <s:FormLayout/>
        </s:layout>
        <s:itemRenderer>
            <fx:Component>
                <s:ItemRenderer>
                    <s:FormItem label="{data.@label}" width="100%"  >
                        <s:TextInput  width="100%"  text="{data.@description}"/>
                    </s:FormItem>
                </s:ItemRenderer>
            </fx:Component>
        </s:itemRenderer>  
    </s:DataGroup>
</s:Scroller>
</s:Application>

谁能告诉我如何对齐表单项标签,同时仍在数据组中使用它们,因为练习的目的是根据输入数据组的数据动态创建表单。

提前致谢。

4

1 回答 1

4

有趣的问题:我解决它很有趣,结果比我预期的要容易。

问题

问题是FormItems 必须是具有 的容器的直接子级FormLayout,但在这种情况下,它FormItem是 的子级,ItemRenderer而后者又是 的子级DataGroup

解决方案

要解决此问题,您可以创建一个FormItem也实现该IItemRenderer接口的子类。这样,DataGroup将知道如何处理这些项目,并且FormItems 将是FormLayout.

编码

首先创建自定义项目渲染器:

public class FormItemRenderer extends FormItem implements IItemRenderer {

    private var _data:Object;
    [Bindable("dataChange")]
    public function get data():Object { return _data; }
    public function set data(value:Object):void {
        _data = value;
        label = value ? value.@label : null;

        if (hasEventListener(FlexEvent.DATA_CHANGE))
            dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE));
    }

    private var _itemIndex:int;
    public function get itemIndex():int { return _itemIndex; }
    public function set itemIndex(value:int):void {
        if (value == _itemIndex) return;

        _itemIndex = value;
        invalidateDisplayList();
    }

    private var _selected:Boolean = false;
    public function get selected():Boolean { return _selected; }
    public function set selected(value:Boolean):void {
        if (value != _selected) {
            _selected = value;
            invalidateDisplayList();
        }
    }

    public function get dragging():Boolean { return false; }
    public function set dragging(value:Boolean):void { }

    public function get showsCaret():Boolean { return false; }
    public function set showsCaret(value:Boolean):void { }

}

我只实现了最低限度的让它工作;您可以稍后添加您需要的内容。还要注意setter
的第二行,我们将XML 节点的属性传递给'属性。这不是一种非常通用的方法,但我想你可以在以后找到解决方案,如果需要的话。datalabelFormItemlabel

现在使用自定义渲染器:

<s:DataGroup dataProvider="{_controls}">
    <s:layout>
        <s:FormLayout/>
    </s:layout>
    <s:itemRenderer>
        <fx:Component>
            <r:FormItemRenderer>
                <s:TextInput width="100%" text="{data.@description}"/>
            </r:FormItemRenderer>
        </fx:Component>
    </s:itemRenderer>
</s:DataGroup>

笔记

您可以将此解决方案与DataGroup开箱即用的方式一起使用,但如果您想将其与List(或任何其他扩展ListBase的组件)一起使用,还需要考虑一件事:
FormLayout不支持布局虚拟化,默认情况下为列表打开(无论如何,对于正常用例来说没有意义)。因此,您必须明确设置useVirtualLayoutfalse避免 NullPointerExceptions。

<s:List dataProvider="{_controls}" useVirtualLayout="false">
    ...
</s:List/>
于 2013-07-30T09:45:38.787 回答