Проблема двусторонней привязки данных

Вот код моего компонента:

<?xml version="1.0" encoding="utf-8"?>
<s:BorderContainer xmlns:fx="http://ns.adobe.com/mxml/2009"
                   xmlns:s="library://ns.adobe.com/flex/spark"
                   xmlns:mx="library://ns.adobe.com/flex/mx"
                   width="950" height="50" creationComplete="this_creationCompleteHandler(event)"
                   currentState="default" enabled="{currentBox!=null}">
    <s:states>
        <s:State name="default"/>
        <s:State name="boxSelected" stateGroups="admin"/>
        <s:State name="textBoxSelected" stateGroups="user"/>
        <s:State name="imageBoxSelected" stateGroups="user"/>
    </s:states>
    <s:layout>
        <s:HorizontalLayout gap="10" horizontalAlign="left" paddingBottom="10" paddingLeft="10"
                            paddingRight="10" paddingTop="10" verticalAlign="middle"/>
    </s:layout>

    <fx:Script>
        <![CDATA[
            import mx.events.FlexEvent;

            public var model:Model;

            private var _currentBox:Box = null;
            [Bindable]
            public function set currentBox(box:Box):void 
            {
                _currentBox = box;
                if(model.userType == Model.USER_TYPE_ADMIN)
                    currentState = "boxSelected";
                else if(box is TextBox)
                    currentState = "textBoxSelected";
                else if(box is ImageBox)
                    currentState = "imageBoxSelected";
                else
                    currentState = "default";
            }

            public function get currentBox():Box
            {
                return _currentBox;
            }

            protected function this_creationCompleteHandler(event:FlexEvent):void
            {
                AppEventBus.instance.addListener(AppEvent.BOX_SELECTED, boxSelectedHandler);
                AppEventBus.instance.addListener(AppEvent.PAGE_SELECTED, pageSelectedhandler);
            }

            protected function boxSelectedHandler(event:AppEvent):void
            {
                currentBox = event.data as Box;
            }

            protected function pageSelectedhandler(event:AppEvent):void
            {
                currentBox = null;
            }

        ]]>
    </fx:Script>
    <fx:Declarations>
        <!-- Place non-visual elements (e.g., services, value objects) here -->
    </fx:Declarations>

    <s:ToggleButton id="secureLockButton" includeIn="admin, user" width="20" height="20"
                    selected="@{currentBox.secured}"
                    styleName="secureButtonStyle"/>
    <s:DropDownList id="fontsList" includeIn="textBoxSelected" width="150" height="20"
                    selectedItem="@{(currentBox as TextBox).font}"
                    dataProvider="{(currentBox as TextBox).fonts}"/>
    <s:DropDownList id="fontSizesList" includeIn="textBoxSelected" width="60" height="20"
                    selectedItem="@{(currentBox as TextBox).fontSize}"
                    dataProvider="{(currentBox as TextBox).fontSizes}"/>
    <s:DropDownList id="boxTypes" includeIn="boxSelected" width="70" height="20"
                    dataProvider="{Box.BOX_TYPES}" selectedItem="{currentBox.boxType}"/>
    <s:TextInput id="boxName" includeIn="boxSelected" width="70" height="20"
                 text="@{currentBox.name}"/>
</s:BorderContainer>

Класс Box имеет двух наследников: TextBox и ImageBox. Все эти классы [Bindable]. В другом компоненте я выбираю объект Box и уведомляю об этом событии компонент выше с помощью EventBus. Я также использую его для передачи выбранного Box объекта. У каждого TextBox объекта есть ArrayCollection доступных размеров шрифта (шрифтов) и один выбранный. Я хочу привязать свой DropDownList к этим значениям двумя способами. Таким образом, DropDownList всегда отображает текущий выбранный размер шрифта (шрифт) поля, и если пользователь выбирает другое значение из списка, оно устанавливается в текущий объект TextBox.

Когда я выбираю объект TextBox в первый раз, все работает нормально, но когда я выбираю другой, я получаю сообщение об ошибке:

RangeError: значение 0 свойства fontSize вне допустимого диапазона в flashx.textLayout.property::Property$/defaultErrorHandler () [C: \ Vellum \ branch \ v2 \ 2.0 \ dev \ output \ openSource \ textLayout \ src \ flashx \ textLayout \ property \ Property.as: 31] в flashx.textLayout.property::Property/setHelper()[C:\Vellum\branches\v2\2.0\dev\output\openSource\textLayout\src\flashx\textLayout\property\Property .as: 230] в flashx.textLayout.formats :: TextLayoutFormat / setStyleByProperty () [C: \ Vellum \ branch \ v2 \ 2.0 \ dev \ output \ openSource \ textLayout \ src \ flashx \ textLayout \ sizes \ TextLayoutFormat.as: 628] в flashx.textLayout.formats :: TextLayoutFormat / set fontSize () [C: \ Vellum \ branch \ v2 \ 2.0 \ dev \ output \ openSource \ textLayout \ src \ flashx \ textLayout \ sizes \ TextLayoutFormat.as: 1044] в spark.core :: CSSTextLayoutFormat () [E: \ dev \ 4.y \ frameworks \ projects \ spark \ src \ spark \ core \ CSSTextLayoutFormat.as: 75] в spark.components :: RichEditableText / updateStylesIfChanged () [E : \ dev \ 4.y \ frameworks \ projects \ spark \ src \ spar k \ components \ RichEditableText.as: 3649] в spark.components :: RichEditableText / commitProperties () [E: \ dev \ 4.y \ frameworks \ projects \ spark \ src \ spark \ components \ RichEditableText.as: 2509] в mx.core :: UIComponent / validateProperties () [E: \ dev \ 4.y \ frameworks \ projects \ framework \ src \ mx \ core \ UIComponent.as: 8219] в mx.managers :: LayoutManager / validateProperties () [ E: \ dev \ 4.y \ frameworks \ projects \ framework \ src \ mx \ manager \ LayoutManager.as: 597] в mx.managers :: LayoutManager / doPhasedInstantiation () [E: \ dev \ 4.y \ frameworks \ проекты \ framework \ src \ mx \ manager \ LayoutManager.as: 813] в mx.managers :: LayoutManager / doPhasedInstantiationCallback () [E: \ dev \ 4.y \ frameworks \ projects \ framework \ src \ mx \ manager \ LayoutManager .as: 1180]

Каким-то образом selectedValue свойство DropDownList становится 0. Что я делаю не так?


person Lingviston    schedule 11.01.2014    source источник


Ответы (1)


Нелегко увидеть, что происходит «под капотом», не отладив это реальное приложение. Вы можете самостоятельно отследить все сеттеры, чтобы увидеть порядок, в котором появляются bindibgs.

Потому что, на мой взгляд, может произойти то, что две привязки (selectedItem и dataProvider) не синхронизированы, как вы хотите. Вы никогда не знаете, что произойдет в первую очередь, и, что более важно, что произойдет внутри этого списка drpdownlist, когда вы установите один из них. В результате в одной точке двусторонняя привязка возвращает selectedItem, который в этот момент имеет значение null, и устанавливает 0 для fontSize (поскольку Number (null) равно 0). И этот 0 приводит к той ошибке, которая возникает где-то еще.

Просто попробуйте, что на самом деле установлено в установщике fontSize (поместите в него trace ()) для начала.

Вы знаете, поскольку двусторонняя привязка кажется хорошей идеей, я всегда возвращался к «классической привязке» с обработкой события изменения (возвращаясь в этот обработчик событий). При использовании двусторонней привязки мы всегда сталкивались с подобной проблемой.

person user3190916    schedule 17.01.2014
comment
Я пришел к тем же мыслям. - person Lingviston; 21.01.2014