Flex - ArrayCollection - 添加和删除filterFunction
我正在使用 Adobe Flash Builder 4 Premium。我有一个 mx:DataGrid
和一个 s:TextInput
,我试图设置一个搜索框,在每次按键时过滤 DataGrid。
此页面显示了我正在尝试做的事情的近乎完美的示例,除了我将其设置在 s:TitleWindow
中,该窗口使用 PopUpManager 作为弹出窗口显示。我尝试过滤的列表可能非常大。它是一个用户名列表,通过 PHP 从 MySQL 数据库中获取。由于它可能太大,我希望列表在主应用程序中填充一次,然后在弹出窗口中引用,这样就不必在用户每次打开弹出窗口时获取所有用户名。
第一次打开弹出窗口时,所有这些都工作正常,但是如果您关闭它并再次打开它,我会收到此运行时错误:
如果我在关闭弹出窗口之前尝试将 filterFunction
设置回 null,也会收到此错误。
请参阅下面的示例代码:
主要应用:
<?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">
<fx:Script>
<![CDATA[
import mx.collections.*;
import mx.managers.PopUpManager;
[Bindable] public var allMembersList:ArrayCollection;
private function openPopup():void
{
var popupInstance:popup = PopUpManager.createPopUp(this as DisplayObject, popup, true) as popup;
PopUpManager.centerPopUp(popupInstance);
}
]]>
</fx:Script>
<s:Button label="Open Popup" click="openPopup()"/>
</s:Application>
弹出窗口:
<?xml version="1.0" encoding="utf-8"?>
<s:TitleWindow xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:model="services.model.*"
tabChildren="false"
close="close()">
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.core.FlexGlobals;
import mx.managers.PopUpManager;
private function getUsers(startsWith:String = ""):void
{
if (FlexGlobals.topLevelApplication.allMembersList == null)
{
FlexGlobals.topLevelApplication.allMembersList = new ArrayCollection();
getUsersResult.token = php.getUsers();
}
FlexGlobals.topLevelApplication.allMembersList.filterFunction = function(item:Object):Boolean
{
return item.username.match(new RegExp("^"+ startsWith, "i"));
};
FlexGlobals.topLevelApplication.allMembersList.refresh();
grdMemberList.dataProvider = FlexGlobals.topLevelApplication.allMembersList;
}
private function getUsersResultHandler():void
{
var users:Object = getUsersResult.lastResult;
for each (var user:Object in users)
FlexGlobals.topLevelApplication.allMembersList.addItem({"username":user.username});
}
private function close():void
{
FlexGlobals.topLevelApplication.allMembersList.filterFunction = null;
FlexGlobals.topLevelApplication.allMembersList.refresh();
PopUpManager.removePopUp(this);
}
]]>
</fx:Script>
<fx:Declarations>
<model:MODEL id="php" fault="{Alert.show('There was a PHP error!\nPlease note the steps taken to produce this error and call support.\n\nError Message: '+ event.fault.faultDetail, 'Error');}" showBusyCursor="false"/>
<s:CallResponder id="getUsersResult" result="getUsersResultHandler()"/>
</fx:Declarations>
<mx:DataGrid id="grdMemberList" creationComplete="getUsers()">
<mx:columns>
<mx:DataGridColumn headerText="Member List" dataField="username"/>
</mx:columns>
</mx:DataGrid>
<s:TextInput id="txtUsername" keyUp="{ if (event.charCode != 13 && event.charCode != 0) getUsers(txtUsername.text); }"/>
</s:TitleWindow>
尽管出现错误,但应用程序似乎仍然按预期工作,但我不喜欢应用程序中出现错误,所以我真的很想找出导致此问题的原因。
谢谢!
I am using Adobe Flash Builder 4 Premium. I have a mx:DataGrid
and a s:TextInput
, and I am trying to set up a search box that filters the DataGrid on each key press.
This page shows a nearly perfect example of what I'm trying to do, except that I'm setting this up in a s:TitleWindow
, which is brought up as a popup using the PopUpManager. The list I'm trying to filter can be very large. It is a list of usernames, fetched from a MySQL database via PHP. Since it can be so large, I want the list to be populated once in the main application and then referenced in the popup window so that it doesn't have to fetch all the usernames each time the user opens the popup.
I have all of this working fine for the first time you bring up the popup, but if you close it and bring it up again, I get this runtime error:
I also get this error if I attempt to set the filterFunction
back to null just before closing the popup.
See sample code below:
Main Application:
<?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">
<fx:Script>
<![CDATA[
import mx.collections.*;
import mx.managers.PopUpManager;
[Bindable] public var allMembersList:ArrayCollection;
private function openPopup():void
{
var popupInstance:popup = PopUpManager.createPopUp(this as DisplayObject, popup, true) as popup;
PopUpManager.centerPopUp(popupInstance);
}
]]>
</fx:Script>
<s:Button label="Open Popup" click="openPopup()"/>
</s:Application>
Popup:
<?xml version="1.0" encoding="utf-8"?>
<s:TitleWindow xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:model="services.model.*"
tabChildren="false"
close="close()">
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.core.FlexGlobals;
import mx.managers.PopUpManager;
private function getUsers(startsWith:String = ""):void
{
if (FlexGlobals.topLevelApplication.allMembersList == null)
{
FlexGlobals.topLevelApplication.allMembersList = new ArrayCollection();
getUsersResult.token = php.getUsers();
}
FlexGlobals.topLevelApplication.allMembersList.filterFunction = function(item:Object):Boolean
{
return item.username.match(new RegExp("^"+ startsWith, "i"));
};
FlexGlobals.topLevelApplication.allMembersList.refresh();
grdMemberList.dataProvider = FlexGlobals.topLevelApplication.allMembersList;
}
private function getUsersResultHandler():void
{
var users:Object = getUsersResult.lastResult;
for each (var user:Object in users)
FlexGlobals.topLevelApplication.allMembersList.addItem({"username":user.username});
}
private function close():void
{
FlexGlobals.topLevelApplication.allMembersList.filterFunction = null;
FlexGlobals.topLevelApplication.allMembersList.refresh();
PopUpManager.removePopUp(this);
}
]]>
</fx:Script>
<fx:Declarations>
<model:MODEL id="php" fault="{Alert.show('There was a PHP error!\nPlease note the steps taken to produce this error and call support.\n\nError Message: '+ event.fault.faultDetail, 'Error');}" showBusyCursor="false"/>
<s:CallResponder id="getUsersResult" result="getUsersResultHandler()"/>
</fx:Declarations>
<mx:DataGrid id="grdMemberList" creationComplete="getUsers()">
<mx:columns>
<mx:DataGridColumn headerText="Member List" dataField="username"/>
</mx:columns>
</mx:DataGrid>
<s:TextInput id="txtUsername" keyUp="{ if (event.charCode != 13 && event.charCode != 0) getUsers(txtUsername.text); }"/>
</s:TitleWindow>
The app still seems to work as expected, despite the error, but I'm not a fan of having errors in my app, so I would really like to figure out what is causing this issue.
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
事实证明问题出在
tabChildren
属性上。文档说不要在 Flex 中使用此属性,而是使用hasFocusableChildren
代替。不知道为什么这个问题只有在我尝试设置filterFunction
时才出现。我将
tabChildren
设置为 false 的原因是,默认的 TAB 键功能(切换焦点)不会发生,这样我就可以自己控制该行为。hasFocusableChildren
属性不起作用(或者至少将其设置为 false 不会阻止 TAB 键切换焦点),因此我可能需要尝试另一种方法来捕获 TAB 键事件,并且阻止它。EDIT:
对于任何感兴趣的人(即使它与原始帖子没有任何关系),解决方案是将:更改
为:
It turns out the problem was with the
tabChildren
property. The documentation says not to use this property in Flex, but to usehasFocusableChildren
instead. Not sure why this problem only showed itself once I was trying to set thefilterFunction
.The reason I was setting
tabChildren
to false was so that the default TAB key functionality (switching focus) would not take place, so that I can control that behavior myself. ThehasFocusableChildren
property doesn't work (or at least, setting it to false doesn't stop the TAB key from switching focus), so I may need to try another means of capturing the TAB key event and stopping it.EDIT:
For any that are interested (even though it doesn't really have anything to do with the original post), the solution was to change:
to:
我从来没有尝试测试你的代码(因为它也需要服务器端),但我认为你不应该将 filterFunction 设置回 null。或者,您可以将其设置为始终返回 true 的函数。
I never try testing your code (because it needs server-side also) but I think you should not set filterFunction back to null. Alternatively, you could set it to a function that always returns true.