我创建了一个基本上是米的组件(扩展了skinnable容器)。组件的外观包含两个矩形(背景和实际仪表)。该组件接收带有以下字段值,max和min的arraycollection(我传递的arraycollection是Bindable)。当我初始化并传递要用于绘制的数据时它非常有效(请记住 - 仅在第一次工作时)。我创建了一个按钮来更改数据数组并显示当前的仪表值。显然,每当我修改我设置用于渲染的ArrayCollection时,仪表的值都在变化。(不想说“dataProvider”,因为它不是Flex数据提供者,只是一个变量)...这里是代码..
public class meter extends SkinnableContainer {
[SkinPart( required = "true" )]
public var meter:spark.primitives.Rect;
[SkinPart( required = "true" )]
public var meterBackground:spark.primitives.Rect;
private var _dataProvider:ArrayCollection;
private var _renderDirty:Boolean = false;
public function Meter() {
super();
}
public function set dataProvider( value:Object ):void {
if ( value )
{
if(value is ArrayCollection)
{
_renderDirty = true;
_dataProvider = value as ArrayCollection;
}
if(_dataProvider)
{
_dataProvider.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, propertyChanged);//used both eventlisteners but none actually ever fire off
_dataProvider.addEventListener(CollectionEvent.COLLECTION_CHANGE,collectionChanged);
}
invalidateDisplayList();//only happens the first time
}
}
private function collectionChanged(event:CollectionEvent):void
{
Alert.show("In collection Change");//this never goes off when I change the "dataProvider"
_renderDirty = true;
invalidateDisplayList();
}
private function propertyChanged(event:PropertyChangeEvent):void
{
Alert.show("In property Change");//this never goes off when I change the "dataProvider"
_renderDirty=true;
invalidateDisplayList();
}
public function get dataProvider():Object {
return _dataProvider;
}
override protected function updateDisplayList( unscaledWidth:Number, unscaledHeight:Number ):void {
if(_dataProvider))
{
var span:Number = unscaledWidth / _dataProvider[0].max;
var meterWidth:Number = _dataProvider[0].value * span;
meter.width = meterWidth;
_renderDirty = false;
}
}
这是我更改“value”字段的mxml代码....
<fx:Script>
<![CDATA[
[Bindable]
private var meterData:ArrayCollection = new ArrayCollection([
{value:80, max:100, min:0}
]);
protected function mySlider_changeHandler(event:Event):void
{
meterData[0].value = Math.round(mySlider.value)*10;
}
protected function button1_clickHandler(event:MouseEvent):void
{
// TODO Auto-generated method stub
var array:ArrayCollection = testMeter.dataProvider as ArrayCollection;
var value:Number = array[0].value as Number;
Alert.show(value.toString());
// testMeter.meter.width= Math.random()*100;
}
]]>//initial value in "meterData" does get drawn...but when it's changed with the slider..nothing happens..
<custom:Meter id="testMeter" dataProvider="{meterData}" />
<s:HSlider id="mySlider"
liveDragging="true"
dataTipPrecision="0"
change="mySlider_changeHandler(event)"
value="3"/>
<s:Button click="button1_clickHandler(event)"/>
你能帮我弄清楚发生了什么吗?谢谢你们!
答案 0 :(得分:3)
问题是您没有重置dataProvider,也没有做任何事情来触发collectionChange事件。我会单独处理每一个。以下是重置dataProvider的方法:
testMeter.dataProvider = newDataPRovider;
但是,你不是那样做的。因此set方法永远不会在第一个初始设置之后执行。
如果您需要触发collectionChange事件,则需要更改集合。你实际上并没有这样做。您正在更改集合中的对象。此代码不会更改集合:
meterData[0].value = Math.round(mySlider.value)*10;
它只更改集合中某个对象的单个属性。尝试这样的事情:
var newObject = meterData[0];
newObject['value'] = Math.round(mySlider.value)*10
meterData.addItem(newObject);
此代码应触发colletionChange事件,即使您的代码没有。
我还有一些想法,与你的主要问题无关。请务必在dataProvider set方法中删除EventListeners,如下所示:
public function set dataProvider( value:Object ):void {
if ( value )
{
// remove the event listeners here before changing the value
// that should allow the object to have no extra 'references' that prevent it from being garbage collected
_dataProvider.removeEventListener(PropertyChangeEvent.PROPERTY_CHANGE, propertyChanged);
_dataProvider.removeEventListener(CollectionEvent.COLLECTION_CHANGE,collectionChanged);
if(value is ArrayCollection)
{
_renderDirty = true;
_dataProvider = value as ArrayCollection;
}
if(_dataProvider)
{
_dataProvider.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, propertyChanged);//used both eventlisteners but none actually ever fire off
_dataProvider.addEventListener(CollectionEvent.COLLECTION_CHANGE,collectionChanged);
}
invalidateDisplayList();//only happens the first time
}
}
你说:
(不想说“dataProvider”,因为它不是Flex dataprovider,只是一个变量)
Flex List,DataGrid或DataGroup上的dataProvider也“只是一个变量”。我不认为“Flex框架”的实现与你所做的完全不同,无论如何。由于您特别期望最小值和最大值,因此您应该使用具有这些显式属性的值对象而不是ArrayCollection。