- 2008年8月29日 06:28
- つくる
DataGridでスクロールバーの右上にコントロールを追加したい場合があります。
たとえば以下のようにデータを更新するためのボタンなどです。
しかしDataGridののデフォルトの仕様では、横スクロールバーの表示/非表示によって、縦スクロールバーの位置とサイズが切り替わるために、ボタン位置がスクロールボタンと重なってしまうことになりうまくいきません。ここでは、その解決策を探っていきます。
以下は、左側が横スクロールが非表示の場合、右側が横スクロールが表示されている場合のDataGridの仕様をあらわすサンプルです。各サンプルの角にある赤い部分に注意すると、縦スクロールバーの位置とサイズが違うのがよくわかると思います。
上記のように縦スクロールバーの位置が上に上がってしまうと追加した更新ボタンがスクロールボタンと重なってしまいます。これを解決するには、DataGridのスクロール表示処理の仕様を変更する必要があります。以下にその方法を記します。
スクロールバーの位置とサイズはDataGridクラスのupdateDisplayList メソッドでコントロールされています。これを変更するためにDataGridのサブクラス(ここではCustomDataGridクラスとする)で、updateDisplayList をオーバーライドします。
CustomDataGrid::updateDisplayList 1413~1443行目
superの呼び出し以前を削除する
/*
// Note: We can't immediately call super.updateDisplayList()
// because the visibleColumns array must be populated first.
// trace(">>updateDisplayList");
if (displayWidth != unscaledWidth - viewMetrics.right - viewMetrics.left)
{
displayWidth = unscaledWidth - viewMetrics.right - viewMetrics.left;
columnsInvalid = true;
}
calculateColumnSizes();
if (itemEditorPositionChanged)
{
itemEditorPositionChanged = false;
// don't do this if mouse is down on an item
// on mouse up, we'll let the edit session logic
// request a new position
if (!lastItemDown)
scrollToEditedItem(editedItemPosition.rowIndex, editedItemPosition.colIndex);
}
*/
CustomDataGrid::updateDisplayList 1437~1445行目
draw系の処理以外を削除する
/*
if (collection && collection.length)
{
setRowCount(listItems.length);
if (listItems.length)
setColumnCount(listItems[0].length);
else
setColumnCount(0);
}
*/
CustomDataGrid::updateDisplayList 1449行目
横スクロールバーの表示/非表示に関わらず縦スクロールバーの位置をヘッダの下に表示するために、以下のif文をverticalScrollBarの条件だけにする。
// If we have a vScroll only, we want the scrollbar to be below
// the header.
/*
if (verticalScrollBar != null && verticalScrollBar.visible &&
(horizontalScrollBar == null || !horizontalScrollBar.visible) &&
headerVisible)
{
*/
if (verticalScrollBar != null && verticalScrollBar.visible)
{
CustomDataGrid::updateDisplayList 1456行目
表示領域の計算結果に関わらず縦スクロールバーの位置をヘッダの下に表示するために、以下のif文が必ずtrueになるようにする。
/*
if (roomForScrollBar(verticalScrollBar,
unscaledWidth-bm.left-bm.right,
unscaledHeight-hh-bm.top-bm.bottom))
{
*/
if(true)
{
CustomDataGrid::updateDisplayList 1491~1501行目
draw系の処理以外を削除する
/*
if (bEditedItemPositionChanged)
{
bEditedItemPositionChanged = false;
// don't do this if mouse is down on an item
// on mouse up, we'll let the edit session logic
// request a new position
if (!lastItemDown)
commitEditedItemPosition(_proposedEditedItemPosition);
_proposedEditedItemPosition = undefined;
itemsSizeChanged = false;
}
*/
updateDisplayListメソッドではprivateなプロパティやメソッドなどの参照があるので、それらは丸々コピー実装し、それにともない必要なクラスをインポートします。
以下のサンプルの左側が変更を加えたCustomDataGrid、右側がデフォルトのDataGridです。両方とも横スクロールバーが表示されていますが、各サンプルの角にある赤い部分に注意すると、縦スクロールバーの位置とサイズが違うのがよくわかると思います。
