Flex: الاستماع إلى CollectionEvent في مكون مخصص
-
29-09-2019 - |
سؤال
(تحرير: لقد قمت بتحرير سؤالي لجعله أكثر بساطة ، آسف إذا كانت بعض الإجابات خارج السياق)
لقد أعددت حالة اختبار مخفضة لسؤالي:
أحاول إنشاء مكون مخصص يتم تغذيته ببيانات XML قادمة من الخادم. مشكلتي هي أن مستمع CollectionEvent لا يتم إطلاقه وبالتالي لم يتم تحديث الملصقات -
Games.mxml (مكون مخصص مع المستمع):
<mx:Script>
<![CDATA[
import mx.events.*;
private var _xlist:XMLList;
[Bindable]
public function get xlist():XMLList {
return _xlist;
}
public function set xlist(x:XMLList):void {
_xlist = x;
trace("set(" + x +")");
list.dataProvider = x;
list.dataProvider.addEventListener(CollectionEvent.COLLECTION_CHANGE, xlistChanged);
}
private function gameLabel(item:Object):String {
return "game: " + item.@label;
}
private function xlistChanged(event:CollectionEvent):void {
trace("xlistChanged(" + event +")");
all.text = "All games: " + _xlist.game.length();
full.text = "Full games: " + _xlist.game.(user.length() == 3).length();
vacant.text = "Vacant games: " + _xlist.game.(user.length() < 3).length();
}
]]>
</mx:Script>
<mx:Label id="all" text="All games"/>
<mx:Label id="full" text="Full games"/>
<mx:Label id="vacant" text="Vacant games"/>
<mx:List id="list" labelFunction="gameLabel"/>
mytest.mxml (انقر فوق الأزرار لتغيير XML):
private function changeXML1():void {
games = <games>
<game label="1">
<user/>
<user/>
<user/>
</game>
<game label="2">
<user/>
<user/>
</game>
<game label="3">
<user/>
<user/>
<user/>
</game>
</games>;
}
private function changeXML2():void {
games = <games>
<game label="A">
<user/>
<user/>
<user/>
</game>
<game label="B">
<user/>
<user/>
</game>
<game label="C">
</game>
</games>;
}
]]>
</mx:Script>
<mx:XML id="games">
<games>
<game label="X">
<user/>
<user/>
</game>
<game label="Y">
<user/>
<user/>
</game>
</games>
</mx:XML>
<mx:Button label="Change XML 1" click="changeXML1()"/>
<mx:Button label="Change XML 2" click="changeXML2()"/>
<my:Games xlist="{games.game}"/>
من فضلك أنصحني ما هو الخطأ.
التحيات ، أليكس
تحديث: edited games.mxml كما اقترح Clownbaby - لا يزال لا يعمل (XlistChanged لم يتم التذرع به أبدًا):
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:my="*" creationComplete="onCreationComplete(event)">
<mx:Script>
<![CDATA[
import mx.events.*;
private var _xlist:XMLList;
[Bindable]
public function get xlist():XMLList {
return _xlist;
}
public function set xlist(x:XMLList):void {
_xlist = x;
list.dataProvider = x;
trace("\n set: " + x);
}
private function gameLabel(item:Object):String {
return "game: " + item.@label;
}
private function onCreationComplete(event:FlexEvent):void {
list.dataProvider.addEventListener(CollectionEvent.COLLECTION_CHANGE, xlistChanged);
}
private function xlistChanged(event:CollectionEvent):void {
all.text = "All games: " + xlist.length();
full.text = "Full games: " + xlist.(user.length() == 3).length();
vacant.text = "Vacant games: " + xlist.(user.length() < 3).length();
}
]]>
</mx:Script>
<mx:Label id="all" text="All games"/>
<mx:Label id="full" text="Full games"/>
<mx:Label id="vacant" text="Vacant games"/>
<mx:List id="list" labelFunction="gameLabel"/>
</mx:VBox>
المحلول
شيئان:
1) السبب في أن الحدث الخاص بك هو عدم إطلاق النار هو أنك تضيف المستمع بعد تعيينك _xlist
.
2) يجب ألا تضيف مستمعًا للحدث داخل Setter على أي حال. يجب عليك إضافتها على أحداث التهيئة أو الإنشاء لمكون Vbox الخاص بك.
تعديل
حسنًا ، بعد النظر إلى التعليمات البرمجية الخاصة بك مرة أخرى ، يمكنني رؤية المشكلة ... لذلك فقط بعض الأشياء.
3) لماذا تسمية طريقة init
, ، عندما يتم استدعاؤه creationComplete
؟ يجب أن تحصل على عادة تسمية أساليب بشكل مناسب. على سبيل المثال ، الطريقة التي يتم استدعاؤها creationComplete
يجب تسمية: onCreationComplete
, ، أو handleCreationComplete
وبهذه الطريقة ، ستعرف ما الذي يفعله رمزك لمدة 6 أشهر على الطريق.
4) هذه هي مشكلتك الرئيسية: أنت تستخدم Getters / Setters بشكل مناسب. إذا كان لديك مجموعة ، فيجب عليك أيضًا تنفيذ getter (إلا إذا كان لديك حقل كتابة فقط). الأهم من ذلك ، يجب عليك استعمال getter للوصول إلى بياناتك. في الخاص بك xListChanged
الطريقة التي لا تستخدمها في Setter التي حددتها ، وبالتالي لا يتم إخبار أي شيء _xlist
تغيرت في الواقع. على هذا النحو ، يجب عليك تغيير الكود الخاص بك إلى:
private var _xlist:XMLListCollection;
[Bindable]
public function get xlist():XMLListCollection { return this._xlist; }
public function set xlist(value:XMLListCollection):void
{
this._xlist = value;
}
كلما أردت الوصول _xlist
, ، استخدم getter. على سبيل المثال ، قم بتغيير dataProvider الخاص بك List
مكون ليكون {xlist}
. و ال xListChanged
يجب أن تستخدم الطريقة getter: xlist
بدلاً من الوصول مباشرة إلى العضو _xlist
.
نصائح أخرى
لماذا لا تفعل هذا فقط:
مجموعة الوظائف العامة مجموعة XList (x: xmllist): void {
_xlist = new XMLListCollection(x); _all.label = 'All (' + _xlist.length + ')'; var full:XMLList = _xlist.source.game.(user.length() == 3); _full.label = 'Full (' + full.length() + ')'; var free:XMLList = _xlist.source.game.(user.length() < 3); _free.label = 'Free (' + free.length() + ')';
}
لا تحتاج إلى مستمع إذا كانت الطريقة الوحيدة لتعيين متغير _xlist المحلي هي إعداد خاصية XLIST.