Flex 4 Custom Component - Как уведомить скин об изменениях свойств? - PullRequest
5 голосов
/ 30 января 2012

У меня есть пользовательский компонент Flex 4+, который я пытаюсь создать, и скин должен знать об изменениях пользовательского свойства.Это свойство будет определять графику на кнопке (и некоторые другие визуальные изменения), но данные будут постоянно меняться, поскольку они будут обновляться таймером.

Я просмотрел невыразимые примеры и все еще не могу получить их.правильный синтаксис или узнайте, как все должно быть разделено.Я посмотрел на переопределение commitProperties и PropertyChangeEvent без успеха.Поэтому у меня есть два вопроса.

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

Опять же, не беспокойтесь так сильноо том, как кожа на самом деле делает то, что она дЭто может измениться (без использования состояний).Я просто пытаюсь понять, как вызывать определенную функцию при изменении связанного свойства.

Спасибо!

Ответы [ 4 ]

5 голосов
/ 01 февраля 2012

Я отправил пользовательское событие при обновлении данных и прослушал его в скине.

Компонент:

<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);
}
3 голосов
/ 30 января 2012

Наличие базового класса для вызова функции на одном конкретном скине может стать неудобным, поскольку это означает, что базовый класс зависит от класса скина, что затрудняет обмен скинов. Есть два хороших способа обойти это:

Опция 1 : переместить iconClass вверх в компонент. Класс скина может быть привязан непосредственно к свойству, а логика для решения, какой значок использовать, может обрабатываться компонентом, а не скином. Это исключает логику из скина и уменьшает количество кода скинов, с которым вам нужно работать.

Опция 2 : добавьте свойство iconData в скин и свяжите его со свойством iconData хост-компонента. В функции установщика вызовите 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" />
1 голос
/ 22 июля 2016

Другое решение общего вопроса, хотя, возможно, и не идеальное в этой ситуации, заключается в вызове skin.invalidateDisplayList () при каждом изменении свойства.Затем в скине переопределяем функцию updateDisplayList и оттуда вызываем функцию, которая реагирует на измененные свойства, а также, очевидно, вызывает функцию в родительском классе.

См. Здесь: https://forums.adobe.com/thread/797247

0 голосов
/ 30 января 2012
<s:BitmapImage source="{hostComponent.iconClass}" />

должно работать


вам не нужно объявлять public var hostComponent: MyButton;

это часть SparkSkin

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...