How Do I Override the Default Behavior For Rendering Data to a Cell?
By default, a data grid table uses a single field object for each cell in a table and assigns the text property of that field to the cell's data. This lesson will show you how to quickly create your own script that determines how data is rendered in the default table cell. This can be useful for rendering HTML and unicode text, trailing off text that is too wide for a column or for coloring particular cells.
Begin With a Data Grid Table
Create a Button
The default column behavior property can be set to a button. The script of the button will be used to fill in each cell in the table.
I'm going to rename the button to My Default Column Behavior.
Set the Script Of The Button
When creating your own default column behavior it is a good idea to start with the script that the data grid uses by default. You can copy the data grid default script easily enough by selecting the button (1) and executing the following statement in the Message Box (2):
set the script of selobj() to the script of the behavior of button "Default Column" of stack "revDataGridLibrary"
Customize Behavior
Now you can customize the behavior however you would like. Here is what the default behavior looks like.
Important: Make sure you include the dgDataControl getProp handler in your script. This is required in order for the data grid to work properly.
Set 'default column behavior' Property
Now you can set the default column behavior property of the data grid. Select the button (1) and execute the following in the Message Box (2):
set the dgProps["default column behavior"] of group "DataGrid 1" to the long id of selobj()
Now it is time to customize your script!
Example: Truncate Tail
As an example, I will show you how to truncate the tail end of every cell whose content is too wide to fit. The data grid provides a helper command named TruncateTail that takes the short id of a field and a string that signifies the text is being truncated. I've added a call to TruncateTail to the FillInData and LayoutControl handlers so that cell contents are truncated when drawn or when a column is resized.
Note: TruncateTail works fairly well for most cases but can cause visual lag if there are lots of cells being displayed that use TruncateTail. You should test your data and table to make sure it performs adequately for your needs.
Quick Tip: You can determine the name of the column that is being rendered by checking the dgColumn property. You could use this property if you only wanted to truncate the text in certain columns:
switch the dgColumn of me
case "Col 1"
case "Col 2"
TruncateTail the short id of me, "..."
break
end switch
Refresh
To see the results, click the Refresh Data Grid button in the Property Inspector (1). Notice how cell contents are no truncated as needed (2).
Example: Coloring Cells
In this example I am going to dim any cell that is empty. Since the default cell consists of a single field object I can just set the opaque to true, set the backgroundcolor and change the blendlevel.
Result
By clicking on the Refresh button (1) I can see the result (2).
Michael
Can't seem to make truncate work... I located the fillinData and LayoutControl handlers in the script of the data grid, but it's not clear to me how they get called.
Trevor DeVore
@Michael: FillInData and LayoutControl are called when the Data Grid is drawing and resizing a row. if you are having trouble with the lesson can you review with me the steps you've taken and where it fails?
Mark Stuart
Also, can't seem to get the TruncateTail to work on one field in the DataGrid. I've put the following in the FillInData and LayoutControl handlers:
TruncateTail the short id of fld "Subject" of me, "..."
It works when I resize the stack smaller, but when resizing the stack wider, the text of field Subject remains as it was when resized smaller.
Trevor DeVore
@Mark: Are resetting the text of the field before calling TruncateTail. Otherwise the existing text that has already been truncated is being truncated again.
Mark Stuart
Hi Trevor,
I can't make sense of you comments, so here's my DataGrid scripts.
The DataGrid template is like this:
Subject Author
Comments
The comments is a multilined text value, so it needs to have the 'fixed control height' set to False.
But at the same time I don't want hundreds of lines to appear in the DataGrid. Maybe display the first 5 comment lines only. This also needs to have the TruncateTail applied to it.
on FillInData script:
set the text of field "Subject" of me to pDataArray["Subject"]
set the text of field "Author" of me to pDataArray["Author"]
set the text of field "Comments" of me to pDataArray["Comments"]
TruncateTail the short id of fld "Subject" of me, "..."
on LayoutControl script:
set the right of fld "Author" of me to item 3 of pControlRect
put the left of fld "Author" of me into tLeft
put the bottom of fld "Subject" of me into tBott
put the rect of fld "Subject" of me into tRect
put tLeft - 10 into item 3 of tRect
set the rect of fld "Subject" of me to tRect
put the rect of fld "Comments" of me into tRect
put item 3 of pControlRect into item 3 of tRect
set the rect of fld "Comments" of me to tRect
put item 2 of tRect \
+ the formattedHeight of fld "Comments" of me - \
the bottomMargin of fld "Comments" of me \
into item 4 of tRect
set the rect of fld "Comments" of me to tRect
put item 4 of tRect into item 4 of pControlRect
set the rect of graphic "Background" of me to pControlRect
TruncateTail the short id of fld "Subject" of me, "..."
So there it is. Am I doing this correctly?
-Mark
Trevor DeVore
@Mark: No, you are not doing it correctly. Your code sets the the text of the "Subject" field in FillInData. It then calls TruncateTail. In LayoutControl you call TruncateTail again. The problem is that in LayoutControl you are truncating text that was already truncated in FillInDAta.
If you look at the step titled "Example: Truncate Tail" you will notice that the text is stored as a custom property of the field in FillInData. The text is then reset in LayoutControl (before TruncateTail is called) using the custom property value.
Kevin11
I created a table, and set up scripts for each column. Then I discovered this lesson, and decided to implement the method of setting the default column behaviour to a button's script, as above. I emptied the original scripts for the column behaviours. Now, the columns do not populate with data, the button script is not invoked, because it still thinks each column has a script so the default is not needed. The empty column scripts magically re-invent themselves to have a onmouseup handler. It seems to be impossible to delete column behaviours once they have been set up, and therefore seems impossible to then invoke a default column behaviour script.
Trevor DeVore
@Kevin11: The Data Grid determines whether or not a column has a custom template based on the presence of a control named after the column in the Row Template group. For example, if you have a column named "Col 1" and your Row Template group has a group named "Col 1" then the Data Grid uses the group "Col 1" instead of any defaults.
When you customized each column using the property inspector, a group named after your column was created in the "Row Template" group (Control A). Control A became the template control for that column. In addition, a button named after your column but with "Behavior" appended to the name was created (Control B). Control B was assigned to the behavior property of Control A.
If you want to start fresh then you need to delete Control A and Control B from the Row Template group. If you use the Application Browser to look at the controls in the Row Template group for your table you will find these controls. Just delete them and then your default column behavior script should start working.
Carles Barbal
The text that is indicated to insert in the Message Box, does not work for me. If I modify it and I put:
set the script of the selobj to the script of the behavior of button "Default Column" of stack "revDataGridLibrary"
It works for me
Carles Barbal
It does not work for me:
set the dgProps["default column behavior"] of group "DataGrid 1" to the long id of selobj()
and I have not found the solution
Elanor Buchanan
Hi Carles
Thanks for brining this to our attention, there was actually an error in the previous line
set the script of selobj() to the script of button "Default Column" of stack "revDataGridLibrary"
should be
set the script of selobj() to the script of the behavior of button "Default Column" of stack "revDataGridLibrary"
I have updated the lesson and if you use the corrected line, followed by
set the dgProps["default column behavior"] of group "DataGrid 1" to the long id of selobj()
That should work.
Kind regards
Elanor