PDA

Просмотр полной версии : Изменение цвета ряда DataGrid в зависимости от значения датапровайдера


baron27
01.02.2007, 21:13
Привет!
Каким образом можно прорисовывать цвет ряда в датагриде в зависимости от значения, полученного из датапровайдера?

Nirth
01.02.2007, 21:47
http://flasher.ru/forum/showpost.php?p=600098&postcount=5

не подойдет?

Nirth
01.02.2007, 22:30
Вообще не совсем понятно.

Дело в том что дата провайдер содержит в себе объекты, которые передаются ячейкам, тоесть дата провайдер не содержит в себе информации для самой колонки.

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

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

Вот например если юзать отдельное свойство colors

package controls
{
import mx.controls.DataGrid;
import mx.core.ClassFactory;
import mx.collections.ArrayCollection;
import mx.controls.dataGridClasses.DataGridColumn;

public class ColoredDataGrid extends DataGrid
{
private var _colors:Array;

public function ColoredDataGrid()
{
super();

itemRenderer = new ClassFactory(ItemRenderer);
}
[Bindable]
[Inspectable]
public function set colors(value:Object):void
{
if(value is ArrayCollection)
{
_colors = (value as ArrayCollection).source;
}
else if(value is Array)
{
_colors = value as Array;
}

for (var i:Number = 0; i < _colors.length; i++)
{
if(columns[i] != null)
{
(columns[i] as DataGridColumn).setStyle("backgroundColor", _colors[i]);
}
}
}
public function get colors():Object
{
return _colors
}
}
}
import mx.controls.Label;
import controls.ColoredDataGrid;
import mx.controls.dataGridClasses.DataGridListData;


class ItemRenderer extends Label
{
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);

var ld:DataGridListData = listData as DataGridListData;
var dg:ColoredDataGrid = ld.owner as ColoredDataGrid;

trace(ld.rowIndex);
trace(this.text);
trace("");

/*if(ld.rowIndex > 0 && dg.colors != null && dg.colors[ld.columnIndex] != null)
{
graphics.beginFill(dg.colors[ld.columnIndex]);
graphics.drawRect(0, 0, unscaledWidth, unscaledHeight);
graphics.endFill();
}*/
}
}

baron27
02.02.2007, 00:30
http://flasher.ru/forum/showpost.php?p=600098&postcount=5

не подойдет?

спасибо. Видел. Наверное придется использовать это.

Кстати, по поводу
>> Вот например если юзать отдельное свойство colors

Цвет надо передавать в датапровайдере? Я не совсем понял. Можешь привести примерчик...

Nirth
02.02.2007, 01:15
В моем случае я цвет подаю через свойство colors


<myNamespace:ColoredDataGrid colors="{[0xF2F2F2, 0xFF6600]}"......

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

baron27
02.02.2007, 02:12
Ага, ясно, спасибо!
Блин, нафига убрали только
dg.setPropertiesAt(2, {backgroundColor:0xFF0000})...

baron27
02.02.2007, 13:01
использовал вариант http://flasher.ru/forum/showpost.php...98&postcount=5

При использовании ColoredDataGrid все почему-то тормозит.

baron27
09.02.2007, 16:09
Переделал немного примере Питера Энта по отрисовке фонов рядов в гриде:

<?xml version="1.0" encoding="utf-8"?>
<mx:DataGrid xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;

public var keyCell:String;

override protected function drawRowBackground(s:Sprite, rowIndex:int, y:Number, height:Number,
color:uint, dataIndex:int):void
{

if (dataIndex > (dataProvider as ArrayCollection).length-1) {
return;
}
var item:Object = (dataProvider as ArrayCollection).getItemAt(dataIndex);

if( item[keyCell] == 0 ) {
color = 0xf97a86;
}
else {
color = 0xFFFFFF;
}
super.drawRowBackground(s,rowIndex,y,height,color,dataIndex);
}


]]>
</mx:Script>
</mx:DataGrid>


Но вот в чем затык: например, датапровайдера хватает на 10 рядов и 10 ряд у нас красный, а теперь, если датапровайдер изменяется до 5 элементов, то эти пять элементов перекрашиваются правильно, а старый 10 ряд так и остается красным. Пробовал всякие там invalidate'ы - не помогает.

Nirth
09.02.2007, 17:20
у меня сейчас времени мало, можешь демонстрацию сделать?

baron27
09.02.2007, 17:35
http://gorbatov.org/tests/coloredDG/

__i
09.02.2007, 17:57
шаманство айтем рендеров это особый раздел флекса..., вобщем в глубине всего этого конкретный экземпляр айтем рендера ни как особо не связан с конкретным элементом (далее "элемент") в дата провайдере. Вернее его связывает свойство айтем рендера(далее "айтем рендер" ))) ) "data" (ну или типа того). Но эта связь очень легко рвущаяся и заменяемая :

В жизни листовые компонеты создают количество айтем рендеров которое помещаеться в видимую область + 1-2 чтобы сделать иллюзию непрерывной прокрутки (ну или если количество элементов помещаеться в сам компонет, то количество айтем рендеров равно ему скролл не отображается). Теперь при прокрутке происходит этакая "карусель", когда айтем рендер скрывается вверху(внизу) то его просто перекидывают вниз (вверх) и меняют ему поле data. Выглядит это гдето так:

1
2 <- первый видимый
3
4
5
6 <- последний видимый

после скрола(проскролили на 2 пункта) получаеться:
5
6 <- первый видимый
1
2
3
4 <- последний видимый

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

Но все в конце концов сводиться к следующему при перестройке листа, лист просто выстраивает свои айтем рендеры как нужно и присваивает им соответствующие положению данные data. Тут вполне вероятно просиходит следующия ситуация. При этом присваивании айтем рендер просто думает что ему "досталась" старые данные и ничего не делает. Инвалидейты/валидейты ему пофигу (он выровнял себя как нужно, покрасил станлартные вещи и забил на остальное). Поэтому тебе нужно переопределить несколько методов у твоего айтем рендера, какие конкретно я тебе не скажу, но вполне вероятно это метод получения данных (setData вроде или data его тебе 100% нужно переопределить) вполне вероятно тот метод который "слушает" изменения внутри элемента(данных) , ну и какие-то методы которые отвечают за отрисовку твоего айтем рендера (скорей всего это будет тотже validate*|invalidate* и в нем ты просто будешь задавать соответствующий стиль ).

Ну и пару слов про секс.
Все кастомные айтем рендеры которые приведены в примерах в виде мхмл это ОТСТОЙ. Они только для красоты и ничего более. Какой-то более менние продвинутый функционал на них построить довольно сложно

Усе типа рассказал, когда выросту может даже напишу умную статью ).

__i
09.02.2007, 18:06
[вырезано много лишних слов из прошлой статьи]
В кратце Нирт дал те самое правильное решение, вернее ссылку на него :D
( http://flasher.ru/forum/showpost.php?p=600098&postcount=5 ) ну разве что нужно убрать апдейтдисплей лист! т.к. они зачем-то все время перерисовывают замечательный айтем. Его нужно заменить на что то более оптимальное

Nirth
09.02.2007, 18:47
__i прав, тебе нужно переопределять itemRenderer.

7thsky™
10.02.2007, 02:24
Согласен, и айтем рендер должен реализовывать mx.controls.listClasses.IDropInListItemRenderer
тогда будет у элемента {get | set} listData ():BaseListData, где в BaseListData есть и rowIndex и columnIndex

собственно Nirth дал самое оптимальное решение

Nirth
10.02.2007, 03:24
А вроде каждый второй компонент (Label\CheckBox и тд) реализуют IDropInLitItemRenderer.

7thsky™
10.02.2007, 10:16
Сanvas не реализует например

baron27
14.02.2007, 13:04
нормальное решение:
http://www.mikenimer.com/index.cfm/2006/10/3/BackgroundRowColor-DataGrid-component

OlenKa
15.02.2007, 15:30
У меня возник вопрос, а как можно поменять цвет строки уже во время работы? например после какого-то действия пользователя?

baron27
16.02.2007, 10:50
У меня возник вопрос, а как можно поменять цвет строки уже во время работы? например после какого-то действия пользователя?

В данном случае - только, если на действия пользователя изменять соответствующим образом датапровайдер.

max_oil
21.04.2008, 11:53
Но вот в чем затык: например, датапровайдера хватает на 10 рядов и 10 ряд у нас красный, а теперь, если датапровайдер изменяется до 5 элементов, то эти пять элементов перекрашиваются правильно, а старый 10 ряд так и остается красным. Пробовал всякие там invalidate'ы - не помогает.

У меня похожая проблема, сначала все отоброжается нормально, но потом когда я меняю датапровайдер, цвета отображаются старые..
пробовал переопределять listData, как советовал 7thsky™, таким способом - не помогает.

private var _listData:BaseListData;

[Bindable("dataChange")]

public function get listData():BaseListData
{
return _listData;
}

public function set listData(value:BaseListData):void
{
_listData = value;
}

Во Флексе я новичок, наверно что-то не то вобще делаю.. Подскажите пожалуйста, что делать надо?

Захаров
29.04.2008, 12:40
в itemRenderer в методе set data удаляйте все предыдущие настройки редерера и будет вам счастье!
Вот пример одного из моих айтимов смысл его в том что бы показывать в виде цветных прямоугольников историю перемещения объекта

package su.quarta.kadry
{
import flash.events.Event;
import mx.containers.Canvas;
import mx.core.UIComponent;
import su.quarta.kadry.webservices.GetRemoveHistoryResultEvent;
import su.quarta.kadry.webservices.KadryWebService;
import mx.core.IDataRenderer;

public class HistoryPanel extends Canvas //DataGridItemRenderer
{
private var c:Canvas = new Canvas();
private var _lineWidth:int=10;
private var _lineHeight:int=20;
private var _data:XML;
private var _dataXML:XML;
private var actualItemRenderer:IDataRenderer
private var kws:KadryWebService = new KadryWebService();

public function HistoryPanel()
{
super();
init();
}
private function init():void
{
kws.addEventListener(GetRemoveHistoryResultEvent.GetRemoveHistory_RESULT,onResult);
}
override public function get data():Object
{
return _data;
}

override public function set data(value:Object):void
{
_data = value as XML ;
removeAllChildren();
create()
}

private function onResult(evt:Event):void
{
create()
}

private function create():void
{
var x:int;
for(var i:int=0;i<this._data.History.item.length();i++)
{
x=i*(_lineWidth+1);
var item:XML = new XML(this._data.History.item[i]);//подставить цвет
var color:String = String(item.@color).replace("#","0x");
var myUIComponent:UIComponent = new UIComponent();
myUIComponent.graphics.beginFill(uint(color));//
myUIComponent.graphics.drawRect(x,0,_lineWidth,_lineHeight);
this.addChild(myUIComponent);
}
}
}
}