Переменные кеша в провайдере данных

У меня есть класс модели с кучей числовых переменных, которые часто меняются. Все они отправляют свои настраиваемые события, поэтому их можно привязать.

В моем пользовательском интерфейсе несколько экземпляров этих классов объединены в ArrayList, который служит поставщиком данных для Spark DataGrid. Переменные класса меняются отлично, так что проблема есть.

Что я хотел бы сделать сейчас, так это изменить цветовое форматирование этих чисел (точнее, соответствующие метки в gridcoloums) в зависимости от входящих данных, так сказать, изменение зеленого цвета, когда новое значение больше, изменить становится красным, когда новое значение меньше старого.

Как я могу заставить это работать? Я думал о каком-то кешировании старого значения, а потом сравнивал старое и новое. Это способ сделать это, и если да, то как? Или есть другой, возможно, более простой способ без необходимости что-либо кэшировать?

Любая помощь приветствуется!

Изменить: на основе примера, приведенного @ NoobsArePeople2, это мой текущий код. Сначала DataGrid. DataProvider - это список ArrayList, содержащий объекты класса myModel.

<s:DataGrid dataProvider="{_listItems}" >
    <s:columns>
        <s:ArrayList>
        <s:GridColumn dataField="change" headerText="Change" itemRenderer="tableCell">
        <s:GridColumn dataField="bid" headerText="Bid" itemRenderer="tableCell">
  ...
</s:DataGrid>

Теперь средство визуализации tableCell;

<s:GridItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" 
            xmlns:s="library://ns.adobe.com/flex/spark" width="100%" height="100%">

<fx:Script>
    <![CDATA[
        private var previousData:Number;
        private var labelColor:uint;
                    private var _data:Object;

        override public function set data(value:Object):void {

            previousData = _data;
            _data = Number(value);
            invalidateProperties();
        }

        override protected function commitProperties():void {
            super.commitProperties();

            if(previousData < data) {
                labelColor = 0x40c040;
            } else if (previousData > data){
                labelColor = 0xf05050;
            } else
                labelColor = 0xc0c0c0;

            itemLabel.setStyle("color", labelColor);
            itemLabel.text = String(_data); 
        }   
    ]]>
</fx:Script>

<s:Label id="itemLabel"/>
</s:GridItemRenderer>

Пока это работает нормально (в отличие от использования свойства данных, которое вызывает неопределенную ошибку), однако при использовании этого самого средства визуализации элементов для нескольких столбцов сетки он использует одни и те же значения для каждого столбца сетки. О чем это?

Изменить: извините, это работает, только если я напрямую обращаюсь к свойству модели, например data.property, чего я не могу. Мне нужен общий рендеринг элементов для всех столбцов.


person AlBirdie    schedule 05.01.2012    source источник


Ответы (2)


Лучше всего использовать настраиваемое средство визуализации элементов. средство визуализации элементов будет иметь свойство data (где data - одно значение от вашего поставщика данных), которое будет установлено для вас, когда ваш поставщик данных изменится в DataGrid. Ты захочешь

  1. Добавьте новую частную переменную previousData типа Object и
  2. Переопределите установщик для data в вашем средстве визуализации элементов.

Ваш сеттер для data будет выглядеть примерно так:

override public function set data(value:Object):void
{
    // If the data hat not changed, don't do anything
    if (data == value) return;

    // Take the current data and store it in previousData
    previousData = data;

    // Update the current data to the new value that was passed in
    // BEGIN EDIT
    // data = value; <-- Previous code example is wrong it should be:
    super.data = value;
    // END EDIT

    // Tell Flex to update the properties of this renderer
    invalidateProperties();
}

Затем в вашем средстве визуализации элементов переопределите метод commitProperties() следующим образом:

override protected function commitProperties():void
{
    super.commitProperties();

    // pseudo code follows
    if (previousData < data)
    {
        labelColor = green;
    }
    else if (previousData > data)
    {
        labelColor = red;
    }
    else
    {
        labelColor = black;
    }

    label.text = data;
    label.color = labelColor;
    // end pseudo code

}

В качестве альтернативы, если вам нужно получить доступ к свойствам data и не хотите жестко указывать значения кода, это должно сработать (примечание: я на самом деле не тестировал этот код, но он должен работать нормально).

override protected function commitProperties():void
{
    super.commitProperties();

    // This assumes your item renderer subclasses [GridItemRenderer][2]
    var dataField:String = column.dataField;
    var previousValue:Object = previousData[dataField];
    var currentValue:Object = data[dataField];

    // pseudo code follows
    if (previousValue < currentValue)
    {
        labelColor = green;
    }
    else if (previousValue > currentValue)
    {
        labelColor = red;
    }
    else
    {
        labelColor = black;
    }

    label.text = data;
    label.color = labelColor;
    // end pseudo code
}
person NoobsArePeople2    schedule 06.01.2012
comment
Спасибо @ NoobsArePeople2 Я понимаю, что вы здесь делаете, и в основном это именно то, что, как я думал, мне нужно. Тем не менее, у меня есть некоторые небольшие проблемы с вашим решением (скажите, пожалуйста, здесь я действительно не работал с рендерами предметов). Во-первых, if (data == value) выдает ошибку undefined. Во-вторых, объект значения будет иметь тип myModel, даже если dataField в соответствующем столбце GridColumn установлен на myModel.change, который является числом. Я добавил свой рендерер (на основе вашего кода) к первоначальному вопросу выше. - person AlBirdie; 09.01.2012
comment
Это потому, что в моем примере кода была ошибка. См. Часть, которая начинается с BEGIN EDIT - person NoobsArePeople2; 09.01.2012
comment
Что-то здесь действительно не так. Несмотря на то, что я получаю правильные значения (включая обновления) в своих столбцах сетки данных БЕЗ средства визуализации элементов, простая трассировка значения, приведенного к Number в средстве визуализации элементов, всегда выводит NaN при каждом обновлении, что я действительно не понимаю как правильные числа отображаются для столбцов в сетке данных без средства визуализации элементов. - person AlBirdie; 10.01.2012
comment
В вашем коде вы устанавливаете значение на _data, вам нужно установить его на data. - person NoobsArePeople2; 10.01.2012
comment
Понятно. Однако это не решает проблему, заключающуюся в том, что мне пришлось бы получить доступ к числовым значениям через data.propertyOfMyModel, что означало бы, что мне пришлось бы писать средства визуализации элементов для каждого отдельного свойства, которое имеет мой класс модели. Я уже думал о доступе к полю данных в gridcoloum изнутри средства визуализации элементов, но похоже, что компоненты Spark не поддерживают это. Я действительно потерялся здесь. - person AlBirdie; 11.01.2012
comment
Если вы создаете подкласс GridItemRenderer вы можете использовать его свойство column, чтобы получить ссылку на GridColumn, которому принадлежит средство визуализации. GridColumn имеет свойство с именем dataField (которое вы установили), которое соответствует именованному свойству в вашем объекте данных. Вы можете использовать это свойство для правильного доступа к data рендерера. Я отредактировал свой ответ, чтобы показать это. - person NoobsArePeople2; 11.01.2012

Я думаю, вам следует создать собственное средство визуализации элементов для своей сетки данных. Здесь вы должны переопределить data сеттер и использовать BindingUtils для обработки изменений полей. Пример использования находится здесь.

Или вы можете переназначить свои данные в средстве визуализации элементов следующим образом:

override public function set data(value:Object):void
{
    if (value == data)
        return;
    myModelInstance = MyModelClass(value);
}

[Bindable]
private var myModelInstance:MyModelClass;

Затем выполните привязку к полям myModelInstance в средстве визуализации элементов MXML.

person Constantiner    schedule 05.01.2012