Ширина колонок в DataGrid в зависимости от контента

93 views
Skip to first unread message

Koptev Andrew

unread,
Aug 25, 2009, 5:17:33 AM8/25/09
to ruFlex
Подскажите, как сделать ширину колонок в DataGrid такой, чтобы текст
во всех ячейках убрался бы без обрезания и прокрутки.

Sergei Shichinov

unread,
Aug 25, 2009, 5:22:17 AM8/25/09
to ruf...@googlegroups.com
что значит "бурался"...

в любом случае - ответ "никак"
потому что датагрид в произвольный момент вермени отображает только часть данных из датапровайдера
и даже если подобрать ширину для дата айтемов которые сейчас отображаются на экране
то после скроллинга все может измениться...

насколько я помню автоматика датагрида подбирает дифлтную ширину колонок либо по ширине названий колонок
либо по первому айтему из датапровайдера...

Koptev Andrew

unread,
Aug 25, 2009, 5:54:33 AM8/25/09
to ruFlex
http://wiki.flash-ripper.com/index.php?title=DataGrid

DataGrid имеет следующие характеристики по умолчанию:
Размер по умолчанию - если таблица пуста, ширина по умолчанию равна
300 px. Если колонки содержат информацию, но не имеют фиксированных
размеров, ширина каждой колонки равна 100 px. По умолчанию
отображаются семь рядов, включая заголовок, каждый ряд высотой 20 px.

On Aug 25, 1:22 pm, Sergei Shichinov <shichinov.ser...@gmail.com>
wrote:

Sergei Shichinov

unread,
Aug 25, 2009, 6:02:04 AM8/25/09
to ruf...@googlegroups.com
да Вы правы по поводу отсутствия какой либо сложной автоматики по вычислению ширины (это List умеет подбирать себе ширину по первым 7 строчкам ;-) )

http://livedocs.adobe.com/flex/3/langref/mx/controls/DataGrid.html
Default size: If the columns are empty, the default width is 300 pixels. If the columns contain information but define no explicit widths, the default width is 100 pixels per column. The DataGrid width is sized to fit the width of all columns, if possible. The default number of displayed rows, including the header is 7, and each row, by default, is 20 pixels high.

и это означает все тот же ответ на Ваш вопрос: "никак"

2009/8/25 Koptev Andrew <kopt...@gmail.com>

Андрей Скорик

unread,
Aug 25, 2009, 9:21:41 AM8/25/09
to ruf...@googlegroups.com
Добавлю что measure у стандартного рендерера ADG утсроен так:

если есть явная ширина родительской колонки - включается механизм
подрезающий текст при необходимости

если ширина колонки неуказана - измеряется текст и measured ширина
рендера выставляется по нему

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

точно не помню что там еще - но если h скрол отключен он старается
запихать все колонки в доступную ширину

советую поковырять и в этом направлении.

у меня не так давно была задача сделать алгоритм подбора оптимальной
ширины колонок грида - я постарался ее спустить на тормозах.. :))

--
С уважением, Скорик Андрей. andrew...@gmail.com

Sergei Shichinov

unread,
Aug 25, 2009, 9:37:39 AM8/25/09
to ruf...@googlegroups.com
у меня не так давно была задача сделать алгоритм подбора оптимальной
ширины колонок грида - я постарался ее спустить на тормозах.. :))

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

Yevgen

unread,
Aug 25, 2009, 10:46:36 AM8/25/09
to ruFlex
On Aug 25, 5:17 am, Koptev Andrew <kopte...@gmail.com> wrote:
> Подскажите, как сделать ширину колонок в DataGrid такой, чтобы текст
> во всех ячейках убрался бы без обрезания и прокрутки.
package hhl.components.grids
{
import flash.text.TextLineMetrics;

import mx.controls.DataGrid;
import mx.controls.dataGridClasses.DataGridColumn;
import mx.controls.dataGridClasses.DataGridItemRenderer;
import mx.controls.listClasses.IDropInListItemRenderer;
import mx.events.*;

public class AutoResizeDataGrid extends DataGrid
{
private var posnew:int;
private var direction:String = '';
/*
override protected function mouseOverHandler(event:MouseEvent):void
{
var item:IListItemRenderer = super.mouseEventToItemRenderer
(event);

// Don't show rollOver effect for Header Items

if (item == null){
return;
}
else {
super.mouseOverHandler(event);
}
}
*/
public function AutoResizeDataGrid()
{
super();
horizontalScrollPolicy = 'auto';
liveScrolling = false;
sortableColumns = false;
addEventListener('creationComplete', newCollection, true, 5);
addEventListener(ScrollEvent.SCROLL, scrollHandler2, false, 5);
//addEventListener('updateComplete', doResize, true, 5);
addEventListener('collectionChange', newCollection, false, 5);
callLater(autoSizeColumns);
}

public function doResize(e:*=null):void {
if ( (e.target==this) && (e.target.listItems.length>0) &&
(e.target.listItems[0].length > 0) ) {
removeEventListener('updateComplete',doResize);
autoSizeColumns();
}
}

public function newCollection(e:*=null):void{
addEventListener('updateComplete', doResize);
}

public function scrollHandler2(e:ScrollEvent):void {
posnew = e.position;
direction = e.direction;
autoSizeColumns();
}

public function autoSizeColumns(e:*=null):void {
var dgCol:*;
var col:int;
var lineMetrics:TextLineMetrics;
var row:int;
var renderer:DataGridItemRenderer;
//Alert.show('resizing');



if (this.columnCount > 0 && dataProvider != null) {

var widths:Array = new Array (columnCount);

for (col = 0; col < widths.length; ++col){
widths[col] = -1;
}

renderer = new DataGridItemRenderer;
addChild(renderer);

for (col = 0; col < widths.length; col++) {
if(columns[col] is DataGridColumn)
dgCol = columns[col] as DataGridColumn;

if(columns[col] is AutoResizeDataGridColumn)
dgCol = columns[col] as AutoResizeDataGridColumn;

renderer.text = dgCol.headerText;

if((dgCol is DataGridColumn) || (dgCol is
AutoResizeDataGridColumn && dgCol.autoSize)){
widths[col] = Math.max(renderer.measuredWidth + 15, widths
[col]);
}
if(dgCol is AutoResizeDataGridColumn && !dgCol.autoSize) {
widths[col] = dgCol.width;
}
}
removeChild(renderer);

if(listItems) {

var len:int = listItems.length;
var maxWidth:int = 0;

for(row = 0; row<len; row++) {
for (col=horizontalScrollPosition; col < widths.length; col++) {
if(listItems[row][col-horizontalScrollPosition] is
IDropInListItemRenderer){
lineMetrics = measureText(IDropInListItemRenderer(listItems
[row][col-horizontalScrollPosition]).listData.label);
widths[col] = Math.max(lineMetrics.width+20, widths[col]);
}
}
}

}

for (col = 0; col < widths.length; ++col){
if (widths[col] != -1){
columns[col].width = widths[col];
dispatchEvent(new DataGridEvent
(DataGridEvent.COLUMN_STRETCH,false,false));
}
}

this.invalidateDisplayList();

if(direction != 'vertical'){
this.horizontalScrollPosition = posnew;
}
//this.invalidateList();


}
} //end function
/*
override protected function mouseOverHandler
(event:MouseEvent):void
{
var item:IListItemRenderer =
super.mouseEventToItemRenderer(event);

// Don't show rollOver effect for Header Items
if (super.isHeaderItemRenderer(item))
return;

super.mouseOverHandler(event);
}
*/
}
}

*****************************************************************************************************************

package hhl.components.grids
{
import mx.controls.dataGridClasses.DataGridColumn;

public class AutoResizeDataGridColumn extends DataGridColumn
{
public function AutoResizeDataGridColumn()
{
super();
}

/***
* autoSize
*
* determines whether the column should be auto re-sized or
not; default=true.
*/
[Inspectable(category="General")]
public var autoSize:Boolean = true;
}
}


Koptev Andrew

unread,
Aug 26, 2009, 3:20:11 AM8/26/09
to ruFlex
Огромная благодарность за код. Проверил - всё работает, то только
DataGrid расширяется по ширине текста, который в названии колонки. А
мне надо в содержимом самой таблицы.

Изменил функцию autoSizeColumns:

public function autoSizeColumns(e:*=null):void {

...


for (col = 0; col < widths.length; col++) {

...
for each(var o:Object in dataProvider.source) {
renderer.text = o[dgCol.dataField];


if((dgCol is DataGridColumn) || (dgCol is AutoResizeDataGridColumn
&& dgCol.autoSize)){
widths[col] = Math.max(renderer.measuredWidth + 15, widths[col]);
}
if(dgCol is AutoResizeDataGridColumn && !dgCol.autoSize) {
widths[col] = dgCol.width;
}
}
}
removeChild(renderer);

...

Андрей Скорик

unread,
Aug 26, 2009, 4:12:21 AM8/26/09
to ruf...@googlegroups.com
Угу .. обо что и речь была.. измерить хидер и установить ширину по
нему - не хитрое дело.

А вот пробежаться по всем итемам измерить каждый и выбрать например
наибольший - уже ресурсоемкая такая задача получается..

>всё работает, то только
> DataGrid расширяется по ширине текста, который в названии колонки. А
> мне надо в содержимом самой таблицы.

Ilja Panin

unread,
Aug 26, 2009, 4:52:44 AM8/26/09
to ruf...@googlegroups.com
>А вот пробежаться по всем итемам измерить каждый и выбрать например
>наибольший - уже ресурсоемкая такая задача получается...

Ну если записей не порядка миллиона то нормально,
если у вас только текстовые поля то можно использовать такой алгоритм:

при получении данных, пробегаетесь по вашим данным и выбираете самые
длинные записи у столбцов, запоминаете их (AS3 довольно быстро гоняет
большие циклы :)
затем используя метод у грида (или конкретного рендера если
используються кастомные стили)
measureHTMLText(str);
или
measureText(str); // (они есть во всех в UIComponent и учитывают его стили)
высчитываете ширину конкретных соответствующих столбцов и сразу
забиваете эту ширину в гриды.

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

--
Ilja Panin
http://the33cows.com

Reply all
Reply to author
Forward
0 new messages