Как вызвать повторный вызов itemRendererFunction при изменении данных в Flex

У меня есть список, который использует itemRendererFunction для получения настраиваемых средств визуализации элементов. Есть ли способ переоценить только один элемент в списке и получить другое средство визуализации элементов?

представьте себе такой код:

есть два средства визуализации элементов ItemRendererOne.mxml и ItemRendererTwo.mxml

Data.as

package {

    public class Data {

        private var _data : Boolean = false;

        [Bindable]
        public function get data():Boolean {
            return _data;
        }

        public function set data(value:Boolean) : void {
            _data = value;
        }

        public function Data(value : Boolean) {
            _data = value;
        }
    }
}

и главное приложение

<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication 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 mx.collections.ArrayList;

            private var dataProvider : ArrayList = new ArrayList([new Data(true), new Data(false)]); 

            public function getItemRenderer(data : Object) : IFactory {
                if (data.data) {
                    return new ClassFactory(ItemRendererOne);
                } else {
                    return new ClassFactory(ItemRendererTwo);
                }
            }

            protected function button1_clickHandler(event : MouseEvent) : void {
                var data : Data = dataProvider.getItemAt(0) as Data;
                data.data = !data.data;
            }

        ]]>
    </fx:Script>

    <s:VGroup>
        <s:List dataProvider="{dataProvider}" itemRendererFunction="{getItemRenderer}" />

        <s:Button click="button1_clickHandler(event)" />
    </s:VGroup>

</s:WindowedApplication>

Обычно, когда кто-то нажимает на кнопку, я хочу, чтобы getItemRenderer вызывался снова, а элемент в списке обновлялся новым средством визуализации элементов.


person lordofthefobs    schedule 30.01.2012    source источник
comment
Не уверен в этом, поэтому я не публикую его как ответ, но попробовали ли вы myListId.invalidateList (), считаете, что это заставит его снова вызвать itemRendererFunction для каждого элемента в списке.   -  person shaunhusain    schedule 31.01.2012
comment
(Я предполагаю, что вы имеете в виду invalidateDisplayList ()), похоже, не работает. Единственный способ обновить средство визуализации элементов - это полностью сбросить поставщик данных. но это приводит к перерисовке всего элемента и вызывает мерцание, которое я не хочу   -  person lordofthefobs    schedule 31.01.2012
comment
Я действительно имел в виду invalidateList (), но я также исхожу из точки зрения в основном Flex 3, считаю, что это был доступный метод в сетке данных (если нет, это должна быть расширенная сетка данных), но это привело к тому, что элементы в списке стали недействительными обращался к ним, я полагаю, помогал нам в прошлом с подобными сценариями. Если вы все еще не нашли жизнеспособного решения, ответьте еще раз, и я постараюсь создать его и выяснить, что нужно делать.   -  person shaunhusain    schedule 01.02.2012
comment
да, похоже, что в Flex 3 есть invalidateList, но нет во Flex 4. В итоге я сделал что-то похожее на решение ниже, которое сработало нормально.   -  person lordofthefobs    schedule 02.02.2012


Ответы (1)


Не уверен насчет Flex 4, так как я в основном работаю с Flex 3, но настройка должна быть близкой.
В принципе, пусть рендер обрабатывает рендеринг.

Ваш список должен выглядеть примерно так.

Есть 3 очень важных переопределения, которые вы можете сделать, которые будут контролировать то, как средство визуализации может реагировать на данные.
1) набор данных для того, когда назначаются новые данные
2) createChildren позволит вам динамически создавать дочерние элементы . Я считаю, что это функция, которую вы ищете в сочетании с набором данных
3) commitProperties - здесь вы назначаете данные дочерним элементам, которые жестко запрограммированы, как мой пример метки или динамически созданные дочерние элементы.

То, что я делал в прошлом, похоже.
Я тестирую данные снова в текущем макете, если это не правильный макет, я его перестраиваю.
Итак, в методе набора данных я тестирую если макет неправильный, я вызываю createChildren ().
Я полагаю, вы могли бы протестировать структуру данных на старых данных перед вызовом super.data в набор данных, но у меня не было таких хороших результатов.

myRenderer.mxml

<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" >
    <mx:Script>
      <![CDATA[
        override public function set data(val:Object):void{
          super.data = val;
          if( !val ){
            return;
          }
          // test data here if current layout is wrong rebuild it by calling createchildren
        }
        override protected function createChildren():void{
          super.createChildren()
          if( this.data == null ){
            return;
          }
          // create your data driven layout here
        }   
        override protected function commitProperties():void{
          super.commitProperties();
          if ( data == null ){
            return;
          }
        }

       ]]>
    </mx:Script>
    <mx:Label id="myLabel" text="{data.someLabelVar} />
</mx:VBox>
person The_asMan    schedule 30.01.2012
comment
Я думал об этом. Технически это не было бы слишком сложно, если бы я использовал несколько состояний. Однако мои средства визуализации элементов довольно сложны, написаны на ActionScript и используют настраиваемый макет ... вся причина, по которой я выбрал средство визуализации элементов AS, состоит в том, чтобы сделать его легким, и я думаю, что добавление всей этой логики в средство визуализации элементов свело бы на нет выгоду .. - person lordofthefobs; 31.01.2012
comment
вы используете средство визуализации элементов для создания классов (ItemRendererOne и ItemRendererTwo) и добавления их в качестве дочерних элементов средства визуализации :) Это проще, чем вы думаете, что половина работы уже сделана. Ах да, и в штатах нет нужды. - person The_asMan; 31.01.2012
comment
хм, интересно ... это сработает ... но это еще один уровень UIComponent. Таким образом, у каждого средства визуализации элементов будут все мои настраиваемые средства визуализации, что кажется излишним. - person lordofthefobs; 31.01.2012
comment
У вас должно быть только 1 средство визуализации элементов. это средство визуализации загрузит другое представление в зависимости от данных. - person The_asMan; 31.01.2012
comment
да, я закончил тем, что сделал что-то вроде этого ... Я все еще не большой поклонник наличия нескольких представлений в средстве визуализации элементов. но он позволяет лучше объединять объекты и облегчает мою жизнь. Я не понимаю, почему вы вызываете createChildren (). вы должны переопределить createChildren () для создания подкомпонентов, но вам не придется вызывать его вручную. или мне что-то здесь не хватает? - person lordofthefobs; 02.02.2012
comment
Обычно я всегда вызываю суперфункцию, если я специально не знаю, что эта функция делает внутри. В этом случае commitProperties будет вызываться в VBox. Не повредит это назвать. Также в этом случае я не хочу переопределять функцию, которую я просто хочу добавить к ее функциональности, переопределив ее, а затем вызвав super, я этого добился. В принципе, если вы не хотите остановить поведение функции по умолчанию, вы всегда должны вызывать super. - person The_asMan; 02.02.2012
comment
Никакие вызовы super - это нормально и в моем случае не требуется. Я спрашивал, почему вы хотите вызвать createChildren () из набора данных. Вы упомянули, что хотите вызвать createChildren () в наборах данных, чтобы перестроить макет, который мне не подходит. Вы должны обновить макет в commitProperties (), например, как применяется переход между состояниями. на самом деле, если вы посмотрите документацию createChildren (), в ней конкретно говорится, что ее не следует вызывать напрямую. - person lordofthefobs; 02.02.2012
comment
В этом случае дочерние элементы / представление будут изменены в зависимости от предоставленных текущих данных. Например, когда ваша структура данных изменяется, вам нужно создать экземпляр другого представления, в это время вам нужно воссоздать дочерние элементы средства визуализации элементов. Потомки рендерера основаны на предоставленных данных. Вот почему вы вызываете create children из метода набора данных. - person The_asMan; 03.02.2012
comment
Да, вы правы, вы не должны называть это напрямую. Я знаю пару причин, по которым вы не должны, однако у вас нет выбора, поскольку вам нужно создавать новых дочерних элементов с разными структурами данных. - person The_asMan; 03.02.2012
comment
но не было бы правильным способом создать всех дочерних элементов в createChildren (), а затем добавить / удалить из списка отображения на commitProperties? Это почти звучит так, как будто вы уничтожаете текущее дочернее представление и создаете (или воссоздаете) новое дочернее представление при изменении данных. На самом деле я даже не отменяю создание дочерних элементов. Я аннулируюProperties () при изменении данных и меняю представления в commitProperties (), и каждое представление создается по запросу с использованием геттеров. - person lordofthefobs; 03.02.2012
comment
Очень хороший момент, похоже, мы оба кое-что узнали :) Теперь я должен обновить старый код :( - person The_asMan; 03.02.2012