为什么 Flex 3 中的 ComboBox 中的标签神秘地消失了?
观察下面的 Flex 程序(我使用的是带有 3.5 SDK 的 Flex Builder 3)。第二个组合框以第一个组合框为条件。如果选择“名字”,则您可以选择“姓氏”。如果选择“无”,则不允许您选择姓氏,而是提示您选择名字。
要了解标签消失的神秘问题,请运行此程序并选择一个名字。然后选择一个姓氏。一切都很好。然后在第一个组合框中选择“无”。第二个组合框的提示变回原来的样子,并且姓氏被删除。一切都还好。然后尝试再次选择名字和姓氏。您将看到,选择名字后,姓氏不会出现,尽管它们的空格会出现(如果您调试程序,正确的数据会出现在数据提供程序中)。
这个“bug”一整天都在折磨我。我在其中实现此行为的项目相当复杂,但此示例基本上说明了正在发生的情况。这是 Flex 中的错误,还是我做错了什么?
谢谢!
<?xml version="1.0" encoding="utf-8"?>
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
public var cbCompanyDP:ArrayCollection = new ArrayCollection( [ { firstName: "None", data: 0 },
{ firstName: "Bob", data: 1 },
{ firstName: "Bart", data: 2 } ] );
[Bindable]
public var cbEmployeeDP:ArrayCollection = new ArrayCollection();
public var employees:ArrayCollection = new ArrayCollection( [ { lastName: "Smith" },
{ lastName: "Smyth" },
{ lastName: "Smick" },
{ lastName: "Smack" } ] );
[Bindable]
public var prompt:String = "Choose First Name first";
public function cbFirstNameChange( value:int ):void
{
if ( value == 0 )
{
employees.removeAll();
setEmpDP( employees );
prompt = "Choose First Name first";
}
else
{
setEmployees();
setEmpDP( employees );
prompt = "Now choose Last Name";
}
}
private function setEmpDP( ac:ArrayCollection ):void
{
cbEmployeeDP = ac;
}
private function setEmployees():void
{
employees = new ArrayCollection( [ { lastName: "Smith" },
{ lastName: "Smyth" },
{ lastName: "Smick" },
{ lastName: "Smack" } ] );
}
]]>
</mx:Script>
<mx:HBox>
<mx:ComboBox dataProvider="{cbCompanyDP}"
id="cbFirstName"
labelField="firstName"
width="200"
change="cbFirstNameChange(cbFirstName.selectedItem.data)"
prompt="Choose a first Name" />
<mx:ComboBox dataProvider="{cbEmployeeDP}"
id="cbLastName"
labelField="lastName"
width="200"
prompt="{prompt}" />
</mx:HBox>
Observe the Flex program below (I'm using Flex Builder 3 w/ 3.5 SDK). The second combobox is conditional on the first. If a 'first name' is chosen, then you are allowed to choose a 'last name'. If 'none' is chosen, then you are not allowed to choose a last name, but rather prompted to choose a first name.
To see the mysterious issue of the disappearing labels, run this program and choose a first name. Then choose a last name. All is well. Then choose 'none' in the first combobox. The prompt of the second combobox changes back, and the last names are removed. All is still well. Then try selecting a first and last name again. You will see that after choosing a first name, the last names do not appear, although the spaces for them do (and if you debug the program, the correct data appears in the dataprovider).
This 'bug' has been killing me on the inside all day. The project in which I'm implementing this behavior is quite a bit more complex, but this sample basically exemplifies what is going on. Is this a bug in Flex, or am I doing something wrong?
Thanks!
<?xml version="1.0" encoding="utf-8"?>
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
public var cbCompanyDP:ArrayCollection = new ArrayCollection( [ { firstName: "None", data: 0 },
{ firstName: "Bob", data: 1 },
{ firstName: "Bart", data: 2 } ] );
[Bindable]
public var cbEmployeeDP:ArrayCollection = new ArrayCollection();
public var employees:ArrayCollection = new ArrayCollection( [ { lastName: "Smith" },
{ lastName: "Smyth" },
{ lastName: "Smick" },
{ lastName: "Smack" } ] );
[Bindable]
public var prompt:String = "Choose First Name first";
public function cbFirstNameChange( value:int ):void
{
if ( value == 0 )
{
employees.removeAll();
setEmpDP( employees );
prompt = "Choose First Name first";
}
else
{
setEmployees();
setEmpDP( employees );
prompt = "Now choose Last Name";
}
}
private function setEmpDP( ac:ArrayCollection ):void
{
cbEmployeeDP = ac;
}
private function setEmployees():void
{
employees = new ArrayCollection( [ { lastName: "Smith" },
{ lastName: "Smyth" },
{ lastName: "Smick" },
{ lastName: "Smack" } ] );
}
]]>
</mx:Script>
<mx:HBox>
<mx:ComboBox dataProvider="{cbCompanyDP}"
id="cbFirstName"
labelField="firstName"
width="200"
change="cbFirstNameChange(cbFirstName.selectedItem.data)"
prompt="Choose a first Name" />
<mx:ComboBox dataProvider="{cbEmployeeDP}"
id="cbLastName"
labelField="lastName"
width="200"
prompt="{prompt}" />
</mx:HBox>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
这里的问题是缺少绑定。
如果更改 ComboBox 的 dataProvider,它不会更改生成的下拉列表的 dataProvider。因此,该框知道新列表,但下拉列表仍然处理旧列表。
要解决此问题,您必须对 ComboBox 进行子类化并重写 set dataProvider 和 get dataProvider (为了对称)。
为了在组合框宽度发生变化时更新下拉列表的宽度,还需要重写另一个函数:
这样它就可以正常工作。
如果需要,您可以在设置函数中检查 selectedIndex 是否为-1(在可编辑框中意味着有手动输入的内容),将其从 super.text 保存并恢复为 super.text (并设置索引设置新的 dataProvider 后,再次更改为 -1)。否则,输入字段中的文本将丢失或被第一个列表元素替换。
The problem here is that there is a binding missing.
If you change the dataProvider of teh ComboBox, it does not change the dataProvider of the generated dropdown. So the box knows the new list, but the dropdown still handles the old.
To fix this, you have to subclass the ComboBox and override set dataProvider and get dataProvider (for symmetry).
To also update the width of the dropdown in case the ComboBox width changed, it is also necessary to override another function:
This way it works as it should.
if you want, you can in the set dunction check whether the selectedIndex is -1 (which on an editable box means that there is manually entered content), save it from super.text and restore it to super.text (and set the index to -1 again) once you have set the new dataProvider. Else the text in the input field will be lost or replaced by the first list element.
如果已经设置了数据提供程序,则不要在 Flex 3.5 中将新的 ArrayCollection 设置为 dataProvider - 设置 dataProvider.source (不进行新引用)
do not set new ArrayCollection to dataProvider in Flex 3.5, if data provider was already set - set dataProvider.source (to not make new reference)
就在昨天我也遇到了同样的问题。这似乎是3.5的一个错误。
当您将一个新的 ArrayCollection 对象分配给组合框中绑定的对象时,就会发生这种情况。如果您单击组合框,它将刷新并显示真实内容。
3.5 中的解决方案:不要将新的 arraycollection 分配给绑定变量。您应该只按照 anton 的说法设置源,或者使用 add/remove/addAll Item 方法。类似这样的方法也应该有效:
I had the same problem just yesterday. It seems to be a bug in 3.5.
It happens when you assign a new ArrayCollection object to the one binded in combobox. If you click in the combo box it will refresh, and show the real content.
The solution to this in 3.5: do not assign a new arraycollection to the binded variable. You should only set the source as said by anton, or utilize the add/remove/addAll Item methods.Something like this should work too:
我尝试使用不同的 SDK(3.2 和 4)并且它正在运行,所以我猜这是 3.5 的错误
I tried with a different SDK (3.2 and 4) and it is working on, so I guess it is a bug from 3.5
看来有两个答案:
是的,这是 Flex 3.5 sdk 中的一个错误,因为它在 4 中不会发生(我没有使用其他 SDK 进行测试)。但是,由于我无法在项目中更改 SDK,因此解决方法出现在另一个问题中:
Flex 3.5.0;在数据提供者更改时更新 ComboBox 显示列表
感谢大家的输入。
Well it appears there are two answers:
Yes, this is a bug in Flex 3.5 sdk, as it does not happen in 4 (I have not tested with other SDKs). However, since I cannot change SDKs mid-project, the workaround appeared in another question:
Flex 3.5.0; Update ComboBox display list upon dataprovider change
Thanks for everyone's input.