2012-01-30 9 views
5

Ho un componente Flex 4+ personalizzato che sto cercando di fare e che la pelle sia a conoscenza delle modifiche a una proprietà personalizzata. Questa proprietà determinerà il grafico sul pulsante (e alcune altre modifiche visive) ma i dati cambieranno costantemente in quanto verrà aggiornato da un timer.Flex 4 Componente personalizzato - Come notificare la pelle delle modifiche alle proprietà?

Ho esaminato esempi indicibili e mi sembra ancora impossibile ottenere la sintassi corretta o scoprire come le cose dovrebbero essere separate. Ho esaminato l'override di commitProperties e PropertyChangeEvent senza successo. Quindi ho due domande.

1) Come è possibile ottenere una notifica di una proprietà associata quando cambia?

2) Se i dati per una proprietà associata del componente è un oggetto, il binding funzionerà correttamente se una proprietà dell'oggetto cambia (o sarebbe meglio passare ciascuna proprietà separatamente)?

Ecco un esempio ridotto di ciò che sto cercando di ottenere.

Il componente si presenta così:

<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> 

sto chiamando in questo modo:

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

Ho un sacco di immagini diverse che potrei essere di carico e così ho temo che il numero di stati (con le combinazioni di su/giù/sopra/disabilitato, ecc. possa sfuggire di mano così il SetIconDisplay sta impostando l'icona, ma la vera chiave è che ho un altro codice in quella funzione che deve essere eseguito quando la proprietà iconData cambia ogni X minuti o così. Così la pelle è qualcosa di simile:

<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"/> 

Anche in questo caso, non si preoccupi tanto di come la pelle è in realtà facendo quello che sta facendo come che probabilmente cambierà (se non utilizzano gli stati). Sto solo cercando di capire come chiamare una funzione specifica quando la proprietà associata viene modificata.

Grazie!

risposta

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

dovrebbe funzionare


non è necessario dichiarare public var hostComponent: MyButton;

è parte di SparkSkin

+1

Date un'occhiata al codice SparkSkin e vi accorgerete che hostComponent non fa parte del SparkSkin. Credo che la proprietà venga creata in fase di compilazione in base ai metadati del componente host. Questo ha senso perché tutti gli skin MXML estendono SparkSkin e quella skin non ha modo di sapere quale dovrebbe essere il tipo di argomento proprietà di hostComponent. In una skin solo ActionScript è necessario creare manualmente la proprietà hostComponent. – JeffryHouser

3

Avendo la classe base chiamare una funzione su una pelle particolare può ottenere scomodo, in quanto significa che la classe di base dipende dalla classe pelle, che rende difficile scambiare pelli . Esistono due modi per aggirare il problema:

Opzione 1: Sposta l'iconaClass nel componente. La classe skin può legarsi direttamente alla proprietà e la logica per decidere quale icona utilizzare può essere gestita dal componente anziché dalla skin. Ciò mantiene la logica fuori dalla pelle e mantiene la quantità di codice di skinning su cui lavorare.

Opzione 2: aggiungere una proprietà iconData allo skin e associarla alla proprietà iconData del componente host. Nella funzione setter, chiama SetIconDisplay quando hai un valore valido. Ciò mantiene le icone incapsulate nella pelle, il che può aiutare se si desidera utilizzare una pelle molto diversa per lo stesso componente.

Modifica: Se stai pensando di creare diverse altre skin che non usano le icone, # 2 è la strada da percorrere. Creare una proprietà sulla pelle in questo modo:

private var _iconData:String; 

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

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

Quindi utilizzare un vincolante per collegarlo al hostComponent:

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

Il componente personalizzato è molto semplice, ma avrò circa 4 o 5 skin diversi per questo. Questa particolare pelle è diversa perché potrebbe avere una di molte icone diverse, alcune animazioni e altre cose uniche al riguardo, ma stavo lottando con quella che è la pratica "migliore" per la logica. L'essere logico nella pelle sembrava avere senso perché è il codice che determina cosa visualizzare. Il codice nel componente non sembrava avere senso perché pensavo che il componente stesso non dovesse sapere o preoccuparsi di come appariva. Vuole solo aggiungere una proprietà per la pelle per determinare cosa fare. – ImAStreamer

+0

@ImAStreamer Sembra che dovresti prendere il secondo approccio e aggiornare lo skin per ottenere la proprietà iconData. Ho aggiornato la risposta con il codice richiesto. –

+0

Mi piace quel secondo approccio. Ho scoperto un altro approccio, che funziona. Non sono sicuro quale sarebbe il preferito. Vedi la mia risposta alla mia stessa domanda. – ImAStreamer

5

ho finito per l'invio di un evento personalizzato, quando i dati vengono aggiornati e ascoltare per esso nella pelle.

La componente:

<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> 

La pelle aggiunge questo:

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

nice one mate, penso che questa sia la strada da percorrere perché se guardi SparkButtonSkin, ha il seguente codice: public function set hostComponent (value: ButtonBase): void { if (_hostComponent) _hostComponent.removeEventListener (" contentChange ", contentChangeHandler); _hostComponent = valore; if (valore) _hostComponent.addEventListener ("contentChange", contentChangeHandler); } – zavr

1

Un'altra soluzione per la questione generale, anche se forse non è l'ideale in questa situazione, è quello di chiamare la pelle. invalidateDisplayList() ogni volta che una proprietà cambia. Quindi, nella skin, sovrascrive la funzione updateDisplayList e da lì chiama una funzione che reagisce alle proprietà modificate, oltre a chiamare ovviamente la funzione sulla classe genitore.

vedere qui: https://forums.adobe.com/thread/797247

Problemi correlati