编译器警告我绑定不起作用,但为什么我运行它确实起作用的应用程序!

发布于 2024-11-16 23:44:59 字数 1332 浏览 0 评论 0原文

下面的 Flex 应用程序生成编译器警告:数据绑定将无法检测对“dp”的分配。这似乎是正确的,因为变量“dp”不是可绑定属性(没有 [Bindable] 元数据标记)。我添加了一个按钮,单击该按钮时会将项目附加到“dp”的后面。尽管编译器警告我不会看到“dp”的更改,但每次单击按钮时列表都会显示新项目!

我不明白为什么我可以看到列表中出现新项目。有人可以解释为什么尽管“dp”不可绑定,但它仍然有效吗?

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" minWidth="955" minHeight="600">
<mx:Script>
    <![CDATA[
        import mx.collections.ArrayCollection;
        import mx.rpc.events.ResultEvent;

        private var arrayData:Array = [
            {name:"banana", cat:"fruit", cost:0.99},
            {name:"bread", cat:"bakery", cost:1.99},
            {name:"orange", cat:"fruit", cost:0.52},
            {name:"donut", cat:"bakery", cost:0.33},
            {name:"apple", cat:"fruit", cost:1.05}];

        private var dp:ArrayCollection = new ArrayCollection(arrayData);

        private function onButtonClick(event:MouseEvent):void
        {
            var obj:Object = new Object();
            obj.name="test";
            obj.cat="testcat";
            obj.cost=666;
            dp.addItem(obj);
        }
    ]]>
</mx:Script>        
<mx:HorizontalList dataProvider="{dp}" labelField="name" columnWidth="100" width="80%" height="50"/>
<mx:Button label="Click me" click="onButtonClick(event)" /> 

The Flex application below generates the compiler warning: Data binding will not be able to detect assignments to 'dp'. This seems correct since the variable 'dp' is not a bindable property (there is no [Bindable] metadata tag). I have added a button which appends items to the back of 'dp' when it is clicked. Although the compiler warns me that I will not see changes to 'dp', the list shows the new item every time the button is clicked!

I do not understand why I can see new items appear in the list. Can someone explain why this still works although 'dp' is not bindable?

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" minWidth="955" minHeight="600">
<mx:Script>
    <![CDATA[
        import mx.collections.ArrayCollection;
        import mx.rpc.events.ResultEvent;

        private var arrayData:Array = [
            {name:"banana", cat:"fruit", cost:0.99},
            {name:"bread", cat:"bakery", cost:1.99},
            {name:"orange", cat:"fruit", cost:0.52},
            {name:"donut", cat:"bakery", cost:0.33},
            {name:"apple", cat:"fruit", cost:1.05}];

        private var dp:ArrayCollection = new ArrayCollection(arrayData);

        private function onButtonClick(event:MouseEvent):void
        {
            var obj:Object = new Object();
            obj.name="test";
            obj.cat="testcat";
            obj.cost=666;
            dp.addItem(obj);
        }
    ]]>
</mx:Script>        
<mx:HorizontalList dataProvider="{dp}" labelField="name" columnWidth="100" width="80%" height="50"/>
<mx:Button label="Click me" click="onButtonClick(event)" /> 

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

苏别ゝ 2024-11-23 23:44:59

编译器的警告是正确的。

编译器警告您,将不会检测到将 dp 值从您指定的初始 ArrayCollection 更改为另一个 ArrayCollection 的赋值。

但是,如果您保留 dp 的值,而仅更改其内容,则您的 将继续工作。

这可能看起来微不足道,但它是一个重要的区别,并且可能会导致应用程序中出现一些非常令人困惑的错误。

不会检测到变量dp 的赋值。但是,对 ArrayCollectionlist 的更改将会发生,因为它们会调度 CollectionChangeEvent

例如:

private var dp:ArrayCollection = new ArrayCollection();

private function test():void
{
    // Here, we don't change the value of dp directly,
    // instead we just modify it's list.
    // The DataGroup will show the strings One,Two
    dp.addItem("One")
    dp.addItem("Two") 

    // Here, we change the actual value of dp, by assigning a 
    // new ArrayCollection to it.
    // This change would not be detected, and the list would continue to show 
    // the contents of the previous value.
    // Additionally, the label will show the string "Length: 2",
    // even though the length is clearly now 3. 
    dp = new ArrayCollection(); 
    dp.addItem("Tahi");
    dp.addItem("Rua");
    dp.addItem("Toru");
}


<s:DataGroup dataProvider="{dp}" />
<s:Label text="Length: {dp.length}" />

The compiler is correct in it's warning.

The compiler is warning you that assignments that change the value of dp from the initial ArrayCollection you specified to another ArrayCollection won't be detected.

However, if you leave the value of dp alone, and only change the contents of it, then your <HorizontalList /> will continue to work.

This may seem trivial, but it's an important distinction, and one that can lead to some very confusing bugs further down the road in your application.

Assignments to the variable dp will not be detected. However, changes to the ArrayCollections list will, because they dispatch a CollectionChangeEvent.

eg:

private var dp:ArrayCollection = new ArrayCollection();

private function test():void
{
    // Here, we don't change the value of dp directly,
    // instead we just modify it's list.
    // The DataGroup will show the strings One,Two
    dp.addItem("One")
    dp.addItem("Two") 

    // Here, we change the actual value of dp, by assigning a 
    // new ArrayCollection to it.
    // This change would not be detected, and the list would continue to show 
    // the contents of the previous value.
    // Additionally, the label will show the string "Length: 2",
    // even though the length is clearly now 3. 
    dp = new ArrayCollection(); 
    dp.addItem("Tahi");
    dp.addItem("Rua");
    dp.addItem("Toru");
}


<s:DataGroup dataProvider="{dp}" />
<s:Label text="Length: {dp.length}" />
放我走吧 2024-11-23 23:44:59

尝试使用:

[Bindable("__NoChangeEvent__")]
private var dp:ArrayCollection = new ArrayCollection(arrayData);

在列表中添加元素怎么样,请参见ListBase的代码:

public function set dataProvider(value:Object):void
{
    if (collection)
    {
        collection.removeEventListener(CollectionEvent.COLLECTION_CHANGE, collectionChangeHandler);
    }

    if (value is Array)
    {
        collection = new ArrayCollection(value as Array);
    }
    else if (value is ICollectionView)
    {
        collection = ICollectionView(value);
    }
    else if (value is IList)
    {
        collection = new ListCollectionView(IList(value));
    }
    else if (value is XMLList)
    {
        collection = new XMLListCollection(value as XMLList);
    }
    else if (value is XML)
    {
        var xl:XMLList = new XMLList();
        xl += value;
        collection = new XMLListCollection(xl);
    }
    else
    {
        // convert it to an array containing this one item
        var tmp:Array = [];
        if (value != null)
            tmp.push(value);
        collection = new ArrayCollection(tmp);
    }
    // get an iterator for the displaying rows.  The CollectionView's
    // main iterator is left unchanged so folks can use old DataSelector
    // methods if they want to
    iterator = collection.createCursor();
    collectionIterator = collection.createCursor(); //IViewCursor(collection);
    // trace("ListBase added change listener");
    collection.addEventListener(CollectionEvent.COLLECTION_CHANGE, collectionChangeHandler, false, 0, true);

    clearSelectionData();

    var event:CollectionEvent = new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
    event.kind = CollectionEventKind.RESET;
    collectionChangeHandler(event);
    dispatchEvent(event);

    itemsNeedMeasurement = true;
    invalidateProperties();
    invalidateSize();
    invalidateDisplayList();
}

所以看一下行:

    collection.addEventListener(CollectionEvent.COLLECTION_CHANGE, collectionChangeHandler, false, 0, true);

Try to use:

[Bindable("__NoChangeEvent__")]
private var dp:ArrayCollection = new ArrayCollection(arrayData);

What about adding elements in list see the code of ListBase:

public function set dataProvider(value:Object):void
{
    if (collection)
    {
        collection.removeEventListener(CollectionEvent.COLLECTION_CHANGE, collectionChangeHandler);
    }

    if (value is Array)
    {
        collection = new ArrayCollection(value as Array);
    }
    else if (value is ICollectionView)
    {
        collection = ICollectionView(value);
    }
    else if (value is IList)
    {
        collection = new ListCollectionView(IList(value));
    }
    else if (value is XMLList)
    {
        collection = new XMLListCollection(value as XMLList);
    }
    else if (value is XML)
    {
        var xl:XMLList = new XMLList();
        xl += value;
        collection = new XMLListCollection(xl);
    }
    else
    {
        // convert it to an array containing this one item
        var tmp:Array = [];
        if (value != null)
            tmp.push(value);
        collection = new ArrayCollection(tmp);
    }
    // get an iterator for the displaying rows.  The CollectionView's
    // main iterator is left unchanged so folks can use old DataSelector
    // methods if they want to
    iterator = collection.createCursor();
    collectionIterator = collection.createCursor(); //IViewCursor(collection);
    // trace("ListBase added change listener");
    collection.addEventListener(CollectionEvent.COLLECTION_CHANGE, collectionChangeHandler, false, 0, true);

    clearSelectionData();

    var event:CollectionEvent = new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
    event.kind = CollectionEventKind.RESET;
    collectionChangeHandler(event);
    dispatchEvent(event);

    itemsNeedMeasurement = true;
    invalidateProperties();
    invalidateSize();
    invalidateDisplayList();
}

So take a look at line:

    collection.addEventListener(CollectionEvent.COLLECTION_CHANGE, collectionChangeHandler, false, 0, true);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文