Проблема с двусторонней привязкой данных
-
26-12-2019 - |
Вопрос
Вот код моего компонента:
<?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
доступных размеров шрифта (fonts) и выбранного.Я хочу связать свою DropDownList
получить эти значения можно двумя способами.Итак DropDownList
всегда отображается выбранный в данный момент размер шрифта поля, и если пользователь выбирает другое значение из списка, оно устанавливается в текущее TextBox
объект.
Когда я выбираю объект TextBox в первый раз, все работает нормально, но когда я выбираю другой, я получаю сообщение об ошибке:
Ошибка диапазона:Значение параметра FontSize 0 находится вне диапазона при flashx.textLayout.property::Property$/defaultErrorHandler()[C:\Vellum\branches\v2\2.0\dev\output\openSource extLayout\src\flashx extLayout\property\Property.as:31] при flashx.textLayout.property::Property/setHelper()[C:\Vellum\branches\v2\2.0\dev\output\openSource extLayout\src\flashx extLayout\property\Property.as:230] во flashx.TextLayout.formats::TextLayoutFormat/setStyleByProperty()[C:\Vellum\branches\v2\2.0\dev\output\openSource extLayout\src\flashx extLayout\formats extLayoutFormat.as:628] во flashx.TextLayout.форматы::TextLayoutFormat/установить fontSize()[C:\Vellum\branches\v2\2.0\dev\output\openSource extLayout\src\flashx extLayout\formats extLayoutFormat.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\spark\components ichEditableText.as:3649] при spark.components::RichEditableText/commitProperties()[E:\dev\4.y\frameworks\projects\spark\src\spark\components ichEditableText.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\managers\LayoutManager.as:597] в mx.managers::LayoutManager/doPhasedInstantiation()[E:\dev\4.y\frameworks\projects\framework\src\mx\managers\LayoutManager.as:813] в mx.managers::LayoutManager/doPhasedInstantiationCallback()[E:\dev\4.y\frameworks\projects\framework\src\mx\managers\LayoutManager.as:1180]
Каким - то образом selectedValue
свойство DropDownList
становится равным 0.Что я делаю не так?
Решение
Нелегко увидеть, что происходит "под капотом", без отладки этого реального приложения.Вы могли бы сами отследить все установщики, чтобы увидеть порядок, в котором происходят привязки.
Потому что, на мой взгляд, может произойти то, что две привязки (SelectedItem и dataProvider) - не синхронизированы, как вы хотели бы.Вы никогда не знаете, какой из них произойдет первым, и, что более важно, что происходит внутри этого drpdownlist, когда вы устанавливаете один из них.Результатом является то, что в одной точке двусторонняя привязка возвращает SelectedItem, который в данный момент равен нулю, и устанавливает 0 в FontSize (потому что Number(null) равно 0).И это 0 приводит к той ошибке, которая возникает где-то в другом месте.
Просто попробуйте то, что обычно задается в FontSize setter (поместите в него trace()) для начала.
Вы знаете, поскольку двусторонняя привязка кажется хорошей идеей, я всегда возвращался к "классической привязке" с обработкой события изменения (установка обратно в этом обработчике событий).Мы всегда сталкивались с какой-то проблемой, подобной этой, при использовании двусторонней привязки.