Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

"SetAll"-like solution for GRID.Column(m.I ).Header1.Click() event

Status
Not open for further replies.

IlyaRabyy

Programmer
Nov 9, 2010
571
US
[purpleface]Colleagues,

I need to have a Grid.Column(m.I).Header1.Click event programmed. Therefore, SetAll method won't do coz it sets property value, not event. That Header1.Click() event code shall set the bound table's index order to the corresponding field's index tag.

The problem is - I dunno how many columns this grid will have on run time, neither the Columns' fields' names: I set the Grid.RecordSource dynamically, at run time, after the User selects the table in the File/Open dialog.

All I know is that the table will have an index tag named the same as the field's name (i.e. field "Tax_Code" will have the index tag "Tax_code").

I could've solved this problem by creating this grid at design time with assuredly excessive number of columns, with Column.Header1.Click() pre-programmed.
Then, after the User have the table selected, bind the latter, field-by-field, to the columns sequentially, and delete the un-used columns.

I did it in the past, but that was quite a tedious and (sigh of shame!) messy job, let alone time-consuming. (Making a custom Column object by sub-classing the basic Column ain't appealing either: it still requires a lot of coding for the run-time dynamic table-to-grid column-by-column binding. :-( )

Is there any other solution, more elegant and less time-consuming?

TIA!



Regards,

Ilya
 
Yes, BIUNDEVENTS can solve that, but you can also design a header class and assign it to the grids headerclass and headerclasslibrary properties. Each column you generate then will be an instance of that header class.
Such a header class should have generic code in its click, for example to set order to an index tag named tagX, where X is the columnorder number.

Then you don't need individual code for each header and both that part of the problem is solved and the part, that you don't know how many columns the grid will have, too. It just puts the task on you to create the appropriate amount of index tags. Another way would be setting the tag name as a property value at runtime, when you know what fields are bound to each column.

Bye, Olaf.
 
Mike,
I guess you mean this:

BINDEVENT(oEventSource, cEvent, oEventHandler, cDelegate [, nFlags])

What, then, should be the oEventSource? (Remind you: I dunno even the number of columns, let alone on which column's header the User has clicked...)

Regards,

Ilya
 
Ilya,

After you have populated the grid (that is, after you know the number of columns) you would loop through the grid's Column collection, calling BINDEVENTS() in each case. The column object would then be the oEventSource parameter.

Something like this:

FOR EACH oCol IN TheGrid.Columns
BINDEVENT(oCol, "Click", oHandler, "MyClick")
ENDFOR

This is off the top of my head. I don't know for sure if it would work. But give it a try.

Mike


__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips, training, consultancy
 
Mike,

How do I indicate in the BINDEVENT() call that this custom method has a parameter (in my case - the header object)? Coz otherwise - how do I address the header that's been clicked in order to find the header's parent's controlSource?

TIA!

Regards,

Ilya
 
Good question, Ilya.

I'm not completely sure, but I think the way to do this would be to call AEVENTS() from within the delegate method (from within MyClick, in my example). That will give you an array containing, amongst other things, a reference to the source object (the header that generated the click). You can then use that object to get to the parent column, which in turn will give you the control source.

By the way, the code snipped I gave you earlier was slightly wrong. You need to pass oCol.Header1 as the source object, rather than just oCol. But you no doubt spotted that yourself.

Mike


__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips, training, consultancy
 
This is a reason, why the approach with a header class and headerclass and headerclasslibrary properties are easier to use than Bindevents. AEVENTs can solve the problem of finding the event source, but binding to events your event handler method must have the same parameterization as the original event, and you can't add further parameters or pass info.

Bye, Olaf.
 
I am not very conversant with Bindevent/Aevent. I did not make efforts to learn them yet.

If I understood your questions correctly:

create grid on the form with just one column.
use fcount() (field count function).

* in the INIT of the form
local t_FieldCount
t_FieldCount = fcount()
with thisform.Grid1
* Setup properties as necessary.
.columncount = t_FieldCount
.deletemark = .f.
.readonly = .f.
.recordmark = .f.
.gridlines = 1
.gridlinecolor = rgb(235,245,235)
.gridlinewidth = 2
.recordsource = t_AliasName
.scrollbars = 2 && Vertical
.RowHeight = 18

for ii = 1 to t_FieldCount
thisform.f_m_SetNextColumn(ii,t_FieldName,Proper(t_FieldName))
* Add other statements as required
endfor
endwith

* Method Name : f_m_SetNextColumn
* Store the following into a method
lparameter p_ColumnNumber, p_ControlSource, p_Header
with thisform.Grid1
ic = alltrim(str(p_ColumnNumber))
.column&ic..width = 60 && Needs some work to set it correctly
.column&ic..controlsource = p_ControlSource
.column&ic..Header1.caption = p_Header

.column&ic..currentcontrol = "Text1"
.column&ic..readonly = .f.
.column&ic..fontsize = 9
.column&ic..backcolor = rgb(190,220,190)

.column&ic..sparse = .t.
.column&ic..readonly = .t.
.column&ic..fontsize = 9
.column&ic..Alignment = 2
* plus plus
endwith
return


* Similarly create method for HeaderClick event where you can
* Method Name : f_m_SetOrder
lpara p_IndexName
set index to &p_IndexName && Check for syntax
* or any other statement as required.
* I do not know how it can be done such that when you click on a header and it trigers call to this meathod.
* may be by using Bindevent, or something.
* Worst scneraio : create grid with max columns, ColumnCount property will automatically reset
* to a actual count (fcount()) at the run time.
* grid1.column1.header1.click
* grid1.column2.header1.click and call to f_m_SetOrder.
*
return





 
* I just read the bindevent() and seems this will work.
* add this line to the for loop
* bindevent(thisform.grid1.column&ic,"click",thisform,"f_m_SetIndex")
for ii = 1 to t_FieldCount
thisform.f_m_SetNextColumn(ii,t_FieldName,Proper(t_FieldName))
ic = alltrim(str(ii))
bindevent(thisform.grid1.column&ic,"click",thisform,"f_m_SetIndex")
* Add other statements as required
endfor

I do not know how to find out which colHeader is clicked at this time of writing.

 
*
* Ref : Borislav Borissov on this forum.
* Ref : Job of Bindevents(), Aevents - MikeLewis
* Method Name : f_m_SetIndex
aevents(a_events,0)
t_ColHeader = a_events[1,1].parent.name
if file(t_colHeader+".idx") && or .ndx
set index to &t_ColHeader
else
* if one does not exist.
index on &t_ColHeader to &t_ColHeader
endif

Hope this will help.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top