2012-01-30 15 views
5

私は作成しようとしているカスタムFlex 4+コンポーネントを持っていて、スキンにカスタムプロパティの変更を認識させる必要があります。このプロパティはボタン上のグラフィック(およびその他の視覚的な変更)を決定しますが、データはタイマーによって更新されるので絶えず変化します。Flex 4カスタムコンポーネント - プロパティの変更をスキンに通知する方法

私は例を見てきましたが、正しい構文を取得できないか、物事をどのように分けるべきかを発見できませんでした。私はcommitPropertiesとPropertyChangeEventをオーバーライドして成功しなかった。だから私は2つの質問があります。

1)バインドされたプロパティが変更されたときに、スキンに通知する方法を教えてください。

2)コンポーネントのバインドされたプロパティのデータがオブジェクトの場合、オブジェクトのプロパティが変更された場合、バインディングは正しく動作しますか(またはそれぞれのプロパティを別々に渡す方が良いでしょうか)?

ここでは、私が達成しようとしているものを切り捨てた例を示します。

コンポーネントは次のようになります。

<s:ButtonBase 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[ 
     private var _iconData:String; 

     [Bindable] 
     public function get iconData():String 
     { 
      return _iconData; 
     } 
     public function set iconData(value:String):void 
     { 
      _iconData = value; 
     } 
    ]]> 
</fx:Script> 

私はこのようにそれを呼んでいる:

<components:MyButton id="myButton" iconData="{myData.curIconTag}" skinClass="skins.MyButtonSkin" /> 

私はロード可能性が異なる画像がたくさんあるので、私は、私はSetIconDisplayがアイコンを設定しているように、上/下/上/下の組み合わせなどが手に入らない状態の数を恐れていますが、実際のキーはその関数内に他のコードがあることですiconDataプロパティがX分ごとに変更されたときに実行する必要があります。

<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:fb="http://ns.adobe.com/flashbuilder/2009" 
    creationComplete="init()"> 

<fx:Metadata> 
    [HostComponent("components.MyButton")] 
</fx:Metadata> 

<s:states> 
    <s:State name="default" /> 
    <s:State name="down"/> 
    <s:State name="up"/> 
    <s:State name="over"/> 
    <s:State name="disabled" /> 
</s:states> 

<fx:Script> 
    <![CDATA[ 
     import components.MyButton; 

     [Embed(source="images/image1.png")] 
     private var icon1:Class; 

     [Embed(source="images/image2.png")] 
     private var icon2:Class; 

     [Embed(source="images/image3.png")] 
     private var icon3:Class; 

     [Bindable] 
     public var hostComponent:MyButton; 

     [Bindable] 
     private var iconClass:Class; 

     private function init():void 
     { 
      iconClass = new Class(); 
     } 

     // how do I get this called when the iconData property on my custom component is changed? 
     private function SetIconDisplay():void 
     { 
      switch (hostComponent.iconData) 
      { 
       case "apple": 
        iconClass=icon1; 
        break; 
       case "orange": 
        iconClass=icon2; 
        break; 
       case "grape": 
        iconClass=icon3; 
        break; 
      } 
     } 
    ]]>   
</fx:Script> 

<s:BitmapImage source="{iconClass}" x="0" y="0" width="180" height="108"/> 

ここでも、肌が実際にそれはおそらく(状態を使用していない)に変更されますと、それはやっているやっている方法に関する限り心配しないでください:だから肌は、このようなものです。私はバインドされたプロパティが変更されたときに特定の関数を呼び出す方法を理解しようとしています。

ありがとうございました!

答えて

0
<s:BitmapImage source="{hostComponent.iconClass}" /> 


を動作するはずです、あなたはプロパティpublic var hostComponentを宣言する必要はありません:MyButtonというの。

それはSparkSkin

+1

はSparkSkinコードを見て、あなたはhostComponentがSparkSkinの一部ではないことがわかります。私は、ホストコンポーネントのメタデータに基づいてコンパイル時にプロパティが作成されると考えています。これは、すべてのMXMLスキンがSparkSkinを拡張し、そのスキンがhostComponentのプロパティ引数型が何であるべきかを知る方法がないため、理にかなっています。 ActionScriptのみのスキンでは、hostComponentプロパティを手動で作成する必要があります。 – JeffryHouser

3

それは、基本クラスがスキンを交換することが困難にスキンクラス、に依存していることを意味する基底クラスは、厄介な得ることができる一つの特定の皮膚上の関数を呼び出すことの一部です。これを回避するには、次の2つの方法があります。

オプション1:アイコンクラスをコンポーネントに移動します。スキンクラスはプロパティに直接バインドでき、使用するアイコンを決定するロジックはスキンではなくコンポーネントで処理できます。これにより、ロジックがスキンから外れてしまい、スキンコードの量が少なくて済むようになります。

オプション2:iconDataプロパティをスキンに追加し、それをホストコンポーネントのiconDataプロパティにバインドします。 Setter関数では、有効な値を持つSetIconDisplayを呼び出します。これにより、アイコンがスキンにカプセル化されたままになります。これは、同じコンポーネントに対して非常に異なるスキンを使用する場合に役立ちます。

を編集します。アイコンを使用しない他のスキンをいくつか作成する予定がある場合は、#2を使用します。そのように皮膚上のプロパティを作成します。

private var _iconData:String; 

public function get iconData():String 
{ 
    return _iconData; 
} 

public function set iconData(value:String):void 
{ 
    _iconData = value; 
    SetIconDisplay() 
} 

その後hostComponentに接続するバインディングを使用します。

<fx:Binding source="hostComponent.iconData" destination="iconData" /> 
+0

カスタムコンポーネントは非常に基本的ですが、私は約4〜5種類のスキンがあります。この特定の肌は、さまざまなアイコン、アニメーション、その他のユニークなものを持つことができるため、違っていますが、私はそのロジックにとって「ベストな」プラクティスとは何かを取り組んでいました。それは、何を表示するかを決定するコードなので、肌の中にあるロジックは理にかなっているようです。コンポーネント自体のコードは、コンポーネントの外観がわからない、または気にしないと思ったので、コンポーネントのコードは意味をなさないようでした。何をすべきかを判断するために、スキンのプロパティを追加するだけです。 – ImAStreamer

+0

@ImAStreamer 2番目の方法を採用し、スキンを更新してiconDataプロパティを取得するように思えます。私は必要なコードで答えを更新しました。 –

+0

私はその2番目のアプローチが好きです。私はもう一つのアプローチを発見しました。どちらが好ましいかわからない。自分の質問に対する私の答えを見てください。 – ImAStreamer

5
データが更新され、それを聞いているとき、私はカスタムイベントをディスパッチすることになった

皮膚に

コンポーネント:

<s:ButtonBase 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 classes.CustomEvent; 

      private var _iconData:String; 

      [Bindable] 
      public function get iconData():String 
      { 
       return _iconData; 
      } 
      public function set iconData(value:String):void 
      { 
       _iconData = value; 
       dispatchEvent(new CustomEvent("iconDataUpdated")); 
      } 
     ]]> 
</fx:Script> 

皮膚は、この追加:

protected function skin_preinitializeHandler(event:FlexEvent):void 
{ 
     hostComponent.addEventListener(CustomEvent.ICON_DATA_UPDATED,SetIconDisplay); 
} 
+0

SparkButtonSkinを見ると、SparkButtonSkinを見ると次のようなコードが表示されるので、これは良い方法だと思う:public function set hostComponent(value:ButtonBase):void { if(_hostComponent) _hostComponent.removeEventListener( " contentChange "、contentChangeHandler); _hostComponent = value; if(値) _hostComponent.addEventListener( "contentChange"、contentChangeHandler); } – zavr

1

一般的な質問に対する別の解決策は、このような状況では、おそらく理想的ではないものの、皮膚を呼び出すことです。プロパティが変更されるたびにinvalidateDisplayList()が呼び出されます。次に、スキンでupdateDisplayList関数をオーバーライドし、そこから変更されたプロパティに反応する関数を呼び出し、親クラスの関数を明示的に呼び出します。

はこちらをご覧ください:https://forums.adobe.com/thread/797247

関連する問題