2012-01-01 18 views
0

私は問題をデモするための非常に簡単なテストケースを用意しました。mx.controls.PopUpButtonに添付されたメニューは変更されません

以下の2つのファイルをFlash Builder 4.6プロジェクトに配置すると、すぐに実行されます。

私の問題は、カスタムのPopUpButtonが変化したことがない私に添付メニューは(わずかに変更された)ということです - あなたはそれの右側にある3つのボタンのいずれかをクリックすると、基本となる配列データプロバイダが変更されたにもかかわらず:

screenshot

AuxButtonTest.mxml:

<?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" 
    xmlns:comps="*" 
    creationComplete="init()"> 

    <fx:Script> 
     <![CDATA[ 
      import mx.controls.Alert; 
      import mx.events.FlexEvent; 

      private const XML1:XML = 
       <pref> 
        <aux event="1">One</aux> 
        <aux event="2">Two</aux> 
        <aux event="3">Three</aux> 
        <aux event="4">Four</aux> 
        <aux event="5">Five</aux> 
       </pref>; 

      private const XML2:XML = 
       <pref> 
        <aux event="1">One</aux> 
        <aux event="2">Two</aux> 
       </pref>; 

      private const XML3:XML = 
       <pref> 
        <aux event="3">Three</aux> 
       </pref>; 

      public function init():void { 
       _auxBtn.update(XML1.aux); 
      } 

      //private function handleAuxChosen(event:PrefEvent):void { 
       //Alert.show(event.toString()); 
      //} 
     ]]> 
    </fx:Script> 

    <s:controlBarContent> 
      <!-- commented: aux_chosen="handleAuxChosen(event)" --> 
     <comps:AuxButton id="_auxBtn" /> 
     <s:Button id="_btn1" label="XML 1" click="_auxBtn.update(XML1.aux);" /> 
     <s:Button id="_btn2" label="XML 2" click="_auxBtn.update(XML2.aux);" /> 
     <s:Button id="_btn3" label="XML 3" click="_auxBtn.update(XML3.aux);" /> 
    </s:controlBarContent> 
</s:Application> 

AuxButton.mxml(私のカスタムコPopUpButtonに基づく数値):

<?xml version="1.0" encoding="utf-8"?> 
<mx:PopUpButton 
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    popUp="{_menu}" 
    creationComplete="init(event)"> 

    <fx:Metadata> 
     <!-- [Event(name="aux_chosen", type="PrefEvent")] --> 
    </fx:Metadata> 

    <fx:Script> 
     <![CDATA[ 
      import mx.controls.Menu; 
      import mx.events.MenuEvent; 
      import mx.events.FlexEvent; 

      private var _str:String; 

      [Bindable] 
      private var _data:Array = new Array(); 

      [Bindable] 
      private var _menu:Menu = new Menu(); 

      private function init(event:FlexEvent):void { 
       _menu.dataProvider = _data; 
       _menu.addEventListener('itemClick', handleMenu); 
       addEventListener('click', handleClick); 
      } 

      public function update(xlist:XMLList):void { 
       _data.length = 0; 
       for each (var xml:XML in xlist) { 
        _data.push({label: xml, event: [email protected]}); 
       } 

       label = _data[0].label; 
       _str = _data[0].event; 

       enabled = true; 
      } 

      private function handleMenu(event:MenuEvent):void { 
       label = event.label; 
       _str = event.item.event; 
      }   

      private function handleClick(event:MouseEvent):void { 
       enabled = false; 
       //dispatchEvent(new PrefEvent(PrefEvent.AUX_CHOSEN, _str)); 
      } 
     ]]> 
    </fx:Script> 

</mx:PopUpButton> 

私はカスタムイベントをコメントアウトしました。ここでは問題ありません。

ボタンを数回クリックしてメニューを表示してください。常に5つの項目があり、間違っています。

更新:答えをいただきありがとうございます。次のコードは今すぐ使用できます。私はまだなぜArrayListがサポートされていないのだろうと思っていますが、ArrayCollectionはうまく動作します。

enter image description here

AuxButtonText.mxml:

<?xml version="1.0" encoding="utf-8"?> 
<mx:PopUpButton 
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    popUp="{_menu}" 
    creationComplete="init(event)"> 

    <fx:Script> 
     <![CDATA[ 
      import mx.controls.*; 
      import mx.events.*; 
      import mx.collections.*; 

      private var _str:String; 

      [Bindable] 
      private var _data:ArrayCollection = new ArrayCollection(); 
      //private var _data:ArrayList = new ArrayList(); 

      [Bindable] 
      private var _menu:Menu = new Menu(); 

      private function init(event:FlexEvent):void { 
       _menu.dataProvider = _data; 
       _menu.addEventListener('itemClick', handleMenu); 
       addEventListener('click', handleClick); 
      } 

      public function update(xlist:XMLList):void { 
       _data.removeAll(); 

       if (xlist == null || xlist.length() == 0) { 
        enabled = false; 
        return; 
       } 

       for each (var xml:XML in xlist) 
        _data.addItem({label: xml, event: [email protected]}); 

       label = _data.getItemAt(0).label; 
       _str = _data.getItemAt(0).event; 

       enabled = true; 
      } 

      private function handleMenu(event:MenuEvent):void { 
       label = event.label; 
       _str = event.item.event; 
      }   

      private function handleClick(event:MouseEvent):void { 
       enabled = false; 
       //dispatchEvent(new PrefEvent(PrefEvent.AUX_CHOSEN, _str)); 
      } 
     ]]> 
    </fx:Script> 

</mx:PopUpButton> 

AuxButton.mxml:

<?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" 
    xmlns:comps="*" 
    initialize="init()"> 

    <fx:Script> 
     <![CDATA[ 
      private const XML1:XML = 
       <pref> 
        <aux event="1">One</aux> 
        <aux event="2">Two</aux> 
        <aux event="3">Three</aux> 
        <aux event="4">Four</aux> 
        <aux event="5">Five</aux> 
       </pref>; 

      private const XML2:XML = 
       <pref> 
        <aux event="1">One</aux> 
        <aux event="2">Two</aux> 
       </pref>; 

      private const XML3:XML = 
       <pref> 
        <aux event="3">Three</aux> 
       </pref>; 

      private const XML4:XML = 
       <pref> 
       </pref>; 

      public function init():void { 
       _auxBtn.update(XML1.aux); 
      } 
     ]]> 
    </fx:Script> 

    <s:controlBarContent> 
     <comps:AuxButton id="_auxBtn" /> 
     <s:Button id="_btn1" label="XML 1" click="_auxBtn.update(XML1.aux);" /> 
     <s:Button id="_btn2" label="XML 2" click="_auxBtn.update(XML2.aux);" /> 
     <s:Button id="_btn3" label="XML 3" click="_auxBtn.update(XML3.aux);" /> 
     <s:Button id="_btn4" label="LEN=0" click="_auxBtn.update(XML4.aux);" /> 
     <s:Button id="_btn5" label="NULL" click="_auxBtn.update(null);" /> 
    </s:controlBarContent> 
</s:Application> 
+0

+!明確に定義された問題と、問題解決の手助けをするのに十分なコードが付いた質問があります。 – JeffryHouser

+0

Ugh; +1を削除するのは遅すぎます。指定したコードは、投稿したスクリーンショットを作成しません。 – JeffryHouser

+0

申し訳ありません。 –

答えて

2

配列は、任意のイベント、その内容の変更を派遣していません。経験則として、[Bindable]を配列に使用し、それをある種のdataProviderとして使用するとです。通常はです。追加/削除はイベントをディスパッチしないため、いずれのコンポーネントでも処理されないため、悪い考えです。

Arrayの代わりに、コンテンツが変更されたときにタイプCollectionEvent.COLLECTION_CHANGEのイベントをディスパッチするArrayCollectionを使用してください。 Flex SDKのほとんどのコンポーネントは、これらのイベントを処理し、それに応じて自身を更新します。したがって、新しいsourceArrayCollectionに割り当てるとにメニュー項目を更新させるCollectionEventが送出されるので、次のコードが機能します。

// you don't need [Bindable] on _data 
private var _data:ArrayCollection = new ArrayCollection(); 

public function update(xlist:XMLList):void 
{ 
    var items:Array = []; 

    for each (var xml:XML in xlist) 
    { 
     items.push({label: xml, event: [email protected]}); 
    } 

    _data.source = items; 

    if (items.length > 0) 
    { 
     label = items[0].label; 
     _str = items[0].event; 
    } 

    enabled = true; 
} 
+1

あなたの答えの理論には多くの間違いがあります。まず、ArrayCollectionを使用していても、そのコレクションにアイテムを追加または削除してもバインディングはトリガーされません。これは、collectionChangeイベントを発生させます。 MXリストベースのクラスには、そのcollectionChangeイベントに応答するコードが組み込まれており、それに応じて表示リストを更新します。 Sparkを信じて、このコードはDataGroupにあります。このアプローチは、バインディングの仕組みとは異なる実装です。次に、_dataが実際には変更されていないため、コード "_data.source = items"はバインディングイベントをトリガーしません。それが指すオブジェクト – JeffryHouser

+0

のプロパティのみ。第3に、アレイ上でBindableを使用することは、通常、悪い考えです。どうして?あなたのコードが問題を解決していると思われます。関連するリストベースのクラスは、sourceプロパティを変更したときに発生するcollectionChangeイベントに応答するため、バインディングのためではありません。 – JeffryHouser

+0

ありがとう、Gerhard - ArrayCollectionは私のためにうまくいきます! (当初は自分でArrayListを試していましたが、何らかの理由でmx.controls.Menuによって正しくレンダリングされませんでした。最新の質問をご覧ください)。また、項目:あなたの提案の配列は省略可能です - 私はArrayCollectionを使用し、それも動作します。 –

1

私の問題は私に添付メニューは(わずかに変更された)ということですカスタム のPopUpButtonは変化しない - 基本となる配列データ プロバイダが

を変化させても、この本明細書中には、あなたの問題があります。メニューのdataProviderを変更するか、プライベート_data変数と同期させるコードはありません。 _data配列は実際には変更されますが、_dataと_menu.dataProviderの間の関係はコーディングされていません。それは、データの変更として変更されることはありません、

 private function init(event:FlexEvent):void { 
      _menu.dataProvider = _data; 
      _menu.addEventListener('itemClick', handleMenu); 
      addEventListener('click', handleClick); 
     } 

しかし:

初期値は、あなたのinitメソッドで設定されています。

ここでは、init()メソッドがcreationCompleteで呼び出されることを追加します。これはコンポーネントが一度完全なライフサイクルを経ることを意味します。 _menuのdataProviderを変更し、新しいdataProviderで再描画するためにライフサイクルを再度実行します。これは通常望ましくないことです。どのイベントが発生したかを理解するには、Flex Component Lifecycleをお読みください。 createChildren()を実行した後、子がサイズ変更されて測定される前に、caleldであるdataProviderをinitializeに設定することをお勧めします。

とにかく、クイックフィックスは自分のアップデートでその場で_menu.dataProviderを変更することです:

 public function update(xlist:XMLList):void { 
      _data.length = 0; 
      for each (var xml:XML in xlist) { 
       _data.push({label: xml, event: [email protected]}); 
      } 

      label = _data[0].label; 
      _str = _data[0].event; 

      enabled = true; 
         // new code 
         _menu.dataProvider = _data; 
     } 
+0

これは私の回避策に似ているようです - _menu.dataProviderを何度も設定しています(XMLデータがサーバーデーモンから来たとき)。 _menuが_dataの内容が変更されたことを検出しないのはなぜですか? –

+0

@AlexanderFarber私は「_データの内容が変更されたことを_メニューが検出するのはなぜですか?」という質問をします。私はあなたが実際にそれらを関連付けるコードを書いていないときに、なぜこれらの2つが関連しているべきだと思うのか混乱しています。変数を変更しても変化しない理由は、変数がどのようにメモリ内の点を指すかについての詳細が含まれます。それはおそらく書いて私に数時間かかるだろう。 – JeffryHouser

+0

初期化についての素晴らしい提案= "...."、ありがとうございます –

関連する問題