Ответ может быть очень очень длинным:)
Начиная с вашего кода, проблема в строке:
mainMxml.removeItem();
Ваш mainMxml
экземпляр - null
, и поэтому у вас есть NPE (исключение нулевого указателя).
Но в целом код показывает, что вы в настоящее время не понимаете Flex, особенно привязку данных. И, конечно, есть проблемы с архитектурой приложения.
Сначала ваша строка:
[Bindable]
public var mainMxml:MainMxml;
ничего не делает.
Привязка данных - это просто способ прослушивания изменений переменной, помеченных метатегом [Bindable]
. [Bindable]
- это не инъекция зависимости, а полная противоположность этому.
Так что никто не установил значение вашего mainMxml
поля. И, по правде говоря, это не правильный способ попытаться ввести туда ценность. Вместо этого вы должны использовать шаблон проектирования Observer и запуск события из вашего компонента:
package events {
public class ClearableTextInputEvent extends Event {
public static const PERFORM_CLEAR:String = "performClear";
public function ClearableTextInputEvent(type:String) {
super(type);
}
}
}
Итак, теперь компонент:
package components {
import flash.events.Event;
import flash.events.MouseEvent;
import mx.events.FlexEvent;
import renderers.TextInputRenderer;
import spark.components.Button;
import spark.components.TextInput;
import spark.events.TextOperationEvent;
[Event(name="performClear", type="events.ClearableTextInputEvent")]
public class ClearableTextInput extends TextInput {
[SkinPart(required="true")]
public var clearButton:Button;
public function ClearableTextInput() {
super();
//watch for programmatic changes to text property
this.addEventListener(FlexEvent.VALUE_COMMIT, textChangedHandler, false, 0, true);
//watch for user changes (aka typing) to text property
this.addEventListener(TextOperationEvent.CHANGE, textChangedHandler, false, 0, true);
}
private function textChangedHandler(e:Event):void {
if (clearButton) {
clearButton.visible = (text.length > 0);
}
}
private function clearClick(e:MouseEvent):void {
dispatchEvent(new ClearableTextInputEvent(ClearableTextInputEvent.PERFORM_CLEAR));
}
override protected function partAdded(partName:String, instance:Object):void {
super.partAdded(partName, instance);
if (instance == clearButton) {
clearButton.addEventListener(MouseEvent.CLICK, clearClick);
clearButton.visible = (text != null && text.length > 0);
}
}
override protected function partRemoved(partName:String, instance:Object):void {
super.partRemoved(partName, instance);
if (instance == clearButton) {
clearButton.removeEventListener(MouseEvent.CLICK, clearClick);
}
}
}
}
Ok. Теперь наш рендер. Там мы должны использовать всплывающее окно события, чтобы сообщить нашему контейнеру списка (я полагаю, это экземпляр MainMxml
) о необходимости удалить строку. Для этого нужно создать класс событий.
NB. Вы можете использовать один и тот же класс событий, но проблема в том, что ваш ClearableTextInput
компонент и средство визуализации элементов имеют разные обязанности
и ClearableTextInput
можно снова использовать в некоторых других средствах визуализации. Рекомендуется создавать разные события для разных уровней вашего приложения для слабой связи:
package events {
public class RemoveRowEvent extends Event {
public static const REMOVE_CURRENT_ROW:String = "removeCurrentRow";
public function RemoveRowEvent(type:String) {
super(type, true);
}
}
}
Теперь ваш рендер:
<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
autoDrawBackground="true" xmlns:components="components.*" width="100%">
<s:layout>
<s:HorizontalLayout/>
</s:layout>
<fx:Script>
<![CDATA[
import mx.core.EdgeMetrics;
import mx.core.UIComponent;
import skins.ClearableTextInputSkin;
]]>
</fx:Script>
<components:ClearableTextInput id="clearTxt" text="{data.label}" skinClass="skins.ClearableTextInputSkin" performClear="dispatchEvent(new RemoveRowEvent(RemoveRowEvent.REMOVE_CURRENT_ROW))" />
</s:ItemRenderer>
И, наконец, в контейнере вашего списка (MainMxml
экземпляр, я полагаю):
…
addEventListener(RemoveRowEvent.REMOVE_CURRENT_ROW, onRowRemove);
…
private function onRowRemove(event:RemoveRowEvent):void {
removeItem();
event.stopImmediatePropagation();
}
Я написал этот черновик в браузере, поэтому, пожалуйста, исправьте импорт и т. Д. Самостоятельно:)