xBox is among my most complicated classes to date due to the fact that I have given this three (3) possible usage. And a new user is getting confused with it that I decided to rush here explanations on its features as I believe not everyone can easily see, despite my examples shown in codes on the sample form, how the class' different features can be utilized to each developer's advantage.
Take a look at this image below where the class is using the Combo Feature (QuickFill + Popup Grid)
But then, the class is designed to be used as just plain quickfill, plain popup/dropdown grid or that combo. Explanations follow:
Plain QuickFill/AutoComplete Feature - is the above image without the popup/dropdown grid. This is where the class gives suggestions on the next possible match based on what you have typed so far by highlighting that suggestion
Quickfill means it will fill the possible remaining values for you. Like in this image above, I just typed A and it results to that. Where the highlighted text is the suggestion based on nearest possible matches.
Quickfill will be in place and fire if you use these properties:
- AutoCompSource = The source table/cursor for searching autocomplete/quickfill
- AutoCompField = the source field of the source table/cursor. This is what gets returned to the class' Value property
- ExtraField = is the field of the source table/cursor of secondary possible return value (aside from AutoCompField)
- ExtraValue = mandates the type of value to be returned (is it character, numeric, etc). If it is numeric, you have to put 0 there. Later I will adjust the class to make this automatic dependent on the type of ExtraField field
One thing you need to realize with Quickfill in place is the class will utilize either SEEK() or LOCATE basing whether AutoCompField is indexed or not. That means your record pointer on the underlying source table changes each time as you type as it will position that to the nearest match.
Another is that with Quickfill in place, the class manipulates the mouse insertion point via SelStart and the way to clear up the previous entry is via double-clicking on it or calling its _Clear() method.
Again, Plain QuickFill does not have the popup grid.
Plain Popup Grid (xBoxGrid subclass) feature is again that above image without the highlighted suggestions. The class performs less manipulations that way and is good for fast searching. It does not manipulate SelStart so it is just like an ordinary textbox with that extra dropdown near matches inside a grid. For you to use this feature, you have to do it in codes. xBoxGrid is affected by 3 events, i.e.,
Init - Where we can set the popup grid, you need to include DODEFAULT() then set the grid via calling _SetGrid() method. Let us take a look into these codes I have responsible for generating the above image:
Lparameters cColumnList, nScrollBar, nWidth, nHeight, nGridLines, cFontName, nFontSize, lNoTitleBar
- Pipe Symbol - To break the Column Header Captions, e.g. Asset|Registration|Asset Type
- Dash Symbol - To instruct by code the width of the column, e.g., Asset-60 or Column 1's width is 60. Default is 80.
While these will be bound by the class later to the fields of the resultant cursor based on the field sequence on SQL SELECT which is done in InteractiveChange event (explained later), you have to realize what you will type here is for the columns' headers only and column widths. And so you can put space if you like such as in Asset Type.
nScrollBar - is for scrollbar property of grid or 2 in this case or just vertical scroll
nWidth - is Grid Width or in example, 580
nHeight - is Grid Max Height or is 200 here. This is max height I set on the above image but is not fixed as popup grid will auto-adjust to smaller based on number of results on the cursor.
nGridLines - is Grid Lines or 2 in this case
cFontName - The font to be used on the grid
nFontSize - The size of the font to be used on the grid
and finally lnoTitleBar - To remove or retain the titlebar of the popup form
Do not get confused with _SetGrid() method. It is just meant to set up the appearance of the dropdown grid. Readying it for the resultant cursor later via _SearchGrid() method.
Actual cursor creation based on what has been typed so far is done here:
Local lcSQL, lcRetVal, lcAssetNo
TEXT TO lcSQL NOSHOW PRETEXT 12
Select t1.assetno, t1.regno, t2.xDescript, t1.assetpk, t1.assignfk From assets t1 ;
LEFT Outer Join adescript t2;
ON t2.descpk = t1.descfk;
where [MySearch] $ t1.assetno OR [MySearch] $ t1.regno OR [MySearch] $ t2.xdescript;
order By 1 ;
into Cursor junkasset nofilter
lcSQL = STRTRAN(m.lcSQL,';','')
While I do it that way, you guys can put the SQL SELECT straight onto the first parameter ignoring local variable usage, your choice. Only that the SQL SELECT needs to be of character type, meaning you have to enclose the whole SQL SELECT with quote, double-quote or bracket. For readability's sake, I myself prefer the above local variable approach.
The above means we are asking it to fire _SearchGrid() method and perform a query (m.lcSQL) on every changes we do (keystrokes) on its textbox section or to search and perform filtering sort of as we type on the resultant cursor. It only has three (3) parameters:
Lparameters cSQL, vValue, vExtraValue
vValue = is the primary value which is what gets returned to the textbox portion. It is a field of your choosing in the resultant cursor. Above, it means we want to return the assetno field record from junkasset cursor
vExtraValue = is the secondary "invisible" value that the class can return, in the example above, assetpk which is an AutoInc Primary Key on my junkasset cursor
Once the popup grid appears, you can easily navigate onto that either via clicking onto it or pressing the down arrow. Any of those two will set the focus onto the popup grid.
Once the popup grid receives focus, it will automatically return the value of the rows in highlight or ActiveRow back to the textbox section. To finalize selection is either:
- Click outside of the popup grid
- Double-click on the selected row
- Press Enter key on the active row
Another Event that can be used here is ProgrammaticChange, where I do manipulations on the other objects of the form based on the return value from the popup grid selection. Its usage is something like this:
._driverpk = junkasset.assignfk
._assetpk = This.ExtraValue
._assetno = Alltrim(This.Value)
Where I transferred the needed values on my form properties so those will be visible to the entire form and call a method that shows the image of the asset plus other things.
ProgrammaticChange is where we can implement immediate actions based on the activerow of the popup grid as we navigate to those records either via arrow keys or mouse click. So as we move through the records of that popup grid, we can update other objects in the form as well
Combo Usage (Both QuickFill and Popup Grid in place)
The image above is the combo approach. While this works good on my end, as I have said, I am not that confident yet that this will give you what you want. So to avoid unknown problem, I suggest for you not to use this yet. Or if you want, use it and if something is wrong, inform me.
Things for your consideration in selecting the usage type:
Quickfill - uses an actual table or cursor and performs either SEEK() or LOCATE. Therefore record pointer changes as we type. It requires manipulation of mouse insertion point via SelStart and storing of what you have typed so far; that to ready it for the next entry properly, you have to either double-click on it for it to fire _Clear() method, or you call the _clear() method yourself.
Plain Popup Grid - creates a cursor that is being filtered as you type based on your WHERE condtion. [MySearch] is mandatory there as the class looks for it and replaces it with what you have typed so far in the textbox section. It creates a cursor that gets rebuilt over and over again filtering it with your WHERE condition as you type.
Keep on checking this post as I will slowly update this with other more properties and features of the class. This will be the help documenation on the proper usage of the class.
A bug I realized only later is popup grid won't work with ShowWindow=2 or Desktop = .T.. Will check that one out one time.
This is it for now. Cheers!