пятница, июня 06, 2008

Один ItemRenderer для нескольких колонок

Столкнулся с задачей отображения в DataGrid одинаковых по сути данных (UNIX_TIMESTAMP), к которым нужно применить ItemRenderer так, чтобы последний знал к какой колонке он применяется. Я нашел два способа это сделать и оба связаны с использованием свойства listData. Свойство listData имеют такие элементы как Text, Label, Button, CheckBox и т.п., то есть те, которые имплементируют интерфейс IDropInListItemRenderer. В данном случае в качестве ItemRenderer мне достаточно использовать Label. Если же необходим какой-нибудь контейнер в качестве рендерера, который не имеет свойства listData по-умолчанию, его необходимо реализовать своими силами.
Итак, первый способ - это назначать данные для рендерера в зависимости от индекса колонки таблицы. Приведу кусок кода:

<mx:Label xmlns:mx="http://www.adobe.com/2006/mxml">
...
override public function set data(value:Object):void
{
super.data = value;
var myListData:DataGridListData = DataGridListData(listData);
var colIndex:int = myListData.columnIndex;
switch (colIndex)
case 1: text = data.date1; break;
case 2: text = data.date2; break;
}
...
</mx:Label>

Здесь мы обращаемся к listData, кастим его к DataGridListData, получаем индекс колонки таблицы и в зависимости от индекса отображаем в колонках date1 или date2. Недостатком этого способа является то, что при добавлении новых колонок перед этими придется переделывать код рендерера и также нельзя перетаскивать колонки. Поэтому рассмотрим второй способ.

<?xml version="1.0" encoding="utf-8"?>
<mx:Label xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import mx.controls.dataGridClasses.DataGridListData;
[Bindable] private var formattedVal:String;

override public function set data(value:Object):void
{
super.data = value;
if (value)
{
var myListData:DataGridListData = DataGridListData(listData);
var dt:Date = new Date();
var cellVal:int = int(data[myListData.dataField]);
dt.time = cellVal*1000;
formattedVal = dateformatter.format(dt);
}
}
]]>
</mx:Script>
<mx:DateFormatter id="dateformatter" formatString="DD.MM.YY J:NN"/>
<mx:text>{formattedVal}</mx:text>
</mx:Label>

В данном случае мы обращаемся не к columnIndex, а к dataField, таким образом получая строку, в которой содержится название поля, из которого мы получаем данные. А с помощью data[myListData.dataField] мы получаем значение этого поля.

4 комментария:

ilja.panin комментирует...

убирай трай кеч!
не нужно так делать )

if (value) //или data
{
//тут наша data|value созрела))
}

Andrey Gorbatov комментирует...

Точно. Исправил. А я то голову ломал:) Спасибо.

GB комментирует...

А может было бы проще отнаследоваться от DataGridColumn (DateDataGridColumn какой-нить). Или задать labelFunction конкретной колонке? Или я не правильно понял задачу.

Andrey Gorbatov комментирует...

В данном случае конечно проще использовать labelFunction. Задача была в общем показать, как можно добраться до данных изнутри, чтобы не плодить несколько itemRenderer'ов для однотипных столбцов.