4 Stimmen

Flex 4 Custom Component - Wie benachrichtigt man Skin über Eigenschaftsänderungen?

Ich habe eine benutzerdefinierte Flex 4+-Komponente, die ich versuche, zu machen und haben die Haut von Änderungen an einer benutzerdefinierten Eigenschaft bewusst sein. Diese Eigenschaft wird die Grafik auf der Schaltfläche (und einige andere visuelle Änderungen) bestimmen, aber die Daten ändern sich ständig, wie es durch einen Timer aktualisiert werden.

Ich habe mir unzählige Beispiele angesehen und scheine immer noch nicht in der Lage zu sein, die Syntax richtig zu verstehen oder herauszufinden, wie die Dinge getrennt werden sollten. Ich habe mir die Überschreibung von commitProperties und das PropertyChangeEvent ohne Erfolg angesehen. Ich habe also zwei Fragen.

1) Wie kann ich erreichen, dass ein Skin über eine gebundene Eigenschaft benachrichtigt wird, wenn sie sich ändert?

2) Wenn die Daten für eine gebundene Eigenschaft der Komponente ein Objekt ist, wird die Bindung ordnungsgemäß funktionieren, wenn eine Eigenschaft des Objekts ändert (oder wäre es besser, jede Eigenschaft separat zu übergeben)?

Hier ist ein kleines Beispiel für das, was ich erreichen möchte.

Die Komponente sieht wie folgt aus:

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

Ich nenne es so:

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

Ich habe eine Menge verschiedener Bilder, die ich laden könnte, und so fürchte ich, dass die Anzahl der Zustände (mit den Kombinationen von oben/unten/über/deaktiviert, etc. kann außer Kontrolle geraten, so dass die SetIconDisplay das Symbol eingestellt ist, aber der eigentliche Schlüssel ist, dass ich anderen Code in dieser Funktion, die ausführen muss, wenn die iconData-Eigenschaft alle X Minuten oder so ändert. Also die Haut ist etwas wie dieses:

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

Auch hier sollten Sie sich nicht so viele Gedanken darüber machen, wie die Haut das tut, was sie tut, denn das wird sich wahrscheinlich ändern (keine Zustände verwenden). Ich versuche nur, herauszufinden, wie man eine bestimmte Funktion aufrufen, wenn die gebundene Eigenschaft geändert wird.

Ich danke Ihnen!

4voto

ImAStreamer Punkte 89

Ich beendete ein benutzerdefiniertes Ereignis zu versenden, wenn die Daten aktualisiert wird und hören für sie in der Haut.

Die Komponente:

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

Die Haut fügt dies hinzu:

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

2voto

Dan Monego Punkte 8752

Wenn die Basisklasse eine Funktion für einen bestimmten Skin aufruft, kann das unangenehm werden, da es bedeutet, dass die Basisklasse von der Skin-Klasse abhängig ist, was den Austausch von Skins erschwert. Es gibt zwei gute Möglichkeiten, dies zu umgehen:

Option 1 : Verschieben Sie die IconClass nach oben in die Komponente. Die Skin-Klasse kann direkt an die Eigenschaft gebunden werden, und die Logik für die Entscheidung, welches Symbol zu verwenden ist, kann von der Komponente statt von der Skin gehandhabt werden. Dadurch wird die Logik aus dem Skin herausgehalten und der Umfang des Skinning-Codes, mit dem Sie arbeiten müssen, wird reduziert.

Option 2 : Fügen Sie dem Skin eine iconData-Eigenschaft hinzu und binden Sie diese an die iconData-Eigenschaft der Host-Komponente. Rufen Sie in der Setter-Funktion SetIconDisplay auf, wenn Sie einen gültigen Wert haben. Dadurch bleiben die Symbole im Skin gekapselt, was hilfreich sein kann, wenn Sie für dieselbe Komponente ein ganz anderes Skin verwenden möchten.

bearbeiten : Wenn Sie vorhaben, mehrere andere Skins zu erstellen, die die Icons nicht verwenden, ist Nr. 2 der richtige Weg. Erstellen Sie eine Eigenschaft auf der Haut wie folgt:

private var _iconData:String;

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

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

Verwenden Sie dann eine Bindung, um sie mit der hostComponent zu verbinden:

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

1voto

Stassa Patsantzis Punkte 440

Eine andere Lösung für die allgemeine Frage, wenn auch vielleicht nicht ideal in dieser Situation, ist zu skin.invalidateDisplayList() aufrufen, wenn eine Eigenschaft ändert. Dann überschreiben Sie im Skin die Funktion updateDisplayList und rufen von dort aus eine Funktion auf, die auf die geänderten Eigenschaften reagiert, und rufen natürlich auch die Funktion der übergeordneten Klasse auf.

Siehe hier: https://forums.adobe.com/thread/797247

0voto

Antonos Punkte 573
<s:BitmapImage source="{hostComponent.iconClass}" />

sollte funktionieren


brauchen Sie nicht zu erklären public var hostComponent:MyButton;

es ist Teil von SparkSkin

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X