Sample of multiple table grid

Posted by jmls on 01-Dec-2008 12:18

I am trying to replace one of my ABL screens that dynamically creates a browse based on data in the database.

I've succeeded in using the grid control for a single table, but am struggling for multiple tables.

If, for example, I have the following:

which are linked in the query

and I wanted to show the ClientGroupName and ClientName

(a) in a single row

(b) grouped by ClientGroup

what would I need ?

Would I need three bands for each of the tables ? How do I specify the table the column belongs to when adding the column to the ultragrid ?

If there is any sample of orders, orderline, customers or anything that resembles this, would someone be so kind as to point me in the right direction.

Thanks

All Replies

Posted by Admin on 01-Dec-2008 12:42

Hi Julian,

I already fought this war:>) Take a look at http://www.psdn.com/library/thread.jspa?threadID=12044&tstart=100.

I believe you'll probably need to use datasets to accomplish. I haven't done any more with joined tables.

JL

Posted by Admin on 02-Dec-2008 02:40

Hi Julian,

yes I'm pretty sure, you need a dataset for this. The UltraGrid only supports a single datasource and the only chance for a structured multi-table UI with a single datasource is the prodataset.

I'm not 100% sure, but you may wanna try the treeview. I can look very similar than the grid (even with columns) and might support more than one bingingsource. At least I do expect it to be more flexible.

Mike

Posted by Peter Judge on 02-Dec-2008 08:28

which are linked in the query

and I wanted to show the ClientGroupName and

ClientName

(a) in a single row

UltraGrids support unbound columns. You could use those and populate the column on the grid's InitializeRow event.

(b) grouped by ClientGroup

Do you mean programatically? You should be able to, along these lines.

gridCustomer:DisplayLayout:ViewStyleBand = ViewStyleBand:OutlookGroupBy.
gridCustomer:DisplayLayout:Bands[0]]> ]]>

(From http://devcenter.infragistics.com/Support/KnowledgeBaseArticle.aspx?ArticleID=1026)

-- peter

Posted by Håvard Danielsen on 02-Dec-2008 12:02

The mentioned thread was discussing hierarchical data (i.e. parent - child).

FOR EACH ClientGroup NO-LOCK,

EACH ClientGroupLink OF ClientGroup NO-LOCK,

FIRST Client OF ClientGroupLink NO-LOCK

This is also a hierarchical query, but the question is how to show ClientGroupName from the ClientGroup table and the ClientName from the Client in a single row.

A view with the ClientGroupLink table as the root should be able to see both of these fields since the relation to these tables identifies a single record.

Subsequently a band on the ClientGroupLink table should in theory be able to see those fields.

As of current you cannot achieve this through the binding.

You could use unbound columns as suggested by Peter.

Another option is to use an UltraDropDown on the relation column.

Take a look in WinGrid/SamplesExplorer/UltraDropDown in the UltraControls samples. It is displaying the itemname in the orderline band even if the band only has orderline.itemnum.

Posted by jmls on 02-Dec-2008 12:51

Weeeeeeelllllllll,

I seem to have been able to do this, by copying code from Jim's example and stripping it down to the bare minimum requirements as a proof of concept.

I created a form, added a ultragrid, and created a method called InitGrid, which I called straight after the initialiseComponent() method.

This works .... shows the LocationGroup Name, followed by the location name, followed by the locationID (I put this in to prove to myself it works!)

Please remember that this is pure POC. Not an example to be used.

Message was edited by:

Julian Lyndon-Smith

changed formatting to make it fit the page better

Posted by Håvard Danielsen on 02-Dec-2008 13:31

Weeeeeeelllllllll,

Indeed.

Posted by jmls on 02-Dec-2008 13:39

Weeeeeeelllllllll,

Indeed.

Heh, I thought that my responses were short and to the point.

However, I cannot decide whether you are expressing surprise or "yeah, well, of course if you do it that way it works, stupid ..."

Posted by Håvard Danielsen on 02-Dec-2008 15:20

I thought that including your "WeeeeeeIIIII" kind of implied some surprise, but I have also been trained to not show surprise when something works unexpectedly...

Posted by jmls on 03-Dec-2008 07:32

I thought that including your "WeeeeeeIIIII" kind of

implied some surprise,

You are entirely correct there. My previous effort had a whole boat-load of additional code to try to achieve the same effect.

This way, is, well, easy .... which makes me suspicious ....

Posted by Håvard Danielsen on 03-Dec-2008 09:52

My previous effort had a whole boat-load of additional code to try to achieve the same effect.

I probably went through some of the same exercises. There is currently no way to do this through the tools and I do not think you can achieve this through methods and properties either.

This way, is, well, easy .... which makes me suspicious ....

There is really no technical reason why it should not work, the query has already done the job of flattening the view.

The Binding to queries chapter (page 4-8) in the documentation actually illustrates this approach.

http://www.psdn.com/library/servlet/KbServlet/download/6151-102-35118/dvngp.pdf

--

You probably have to take some additional care in the update logic to prevent updates to the Client.ClientName or Location.iLocationId in this view, since a single Client or Location data row is represented in multiple query rows.

Posted by jmls on 04-Dec-2008 09:56

You probably have to take some additional care in the

update logic to prevent updates to the

Client.ClientName or Location.iLocationId in this

view, since a single Client or Location data row is

represented in multiple query rows.

Yeah, this is read-only.

Now, what would be the best way of getting the specific row(s) when the row is double-clicked ? A hidden column holding the rowid/guid/id ? Can you bind the :tag property of a row to the rowid/guid/id of the table row ?

Posted by Håvard Danielsen on 04-Dec-2008 12:31

The BindingSource keeps the query synchronized with the grid all the time, so you can use the query and buffers as you would in a standard ABL solution.

If your app/architecture do not have access to the query and buffer then you could use the BindingSource's CurrentChanged event to keep track of it, for example by grabbing the BindingSource:handle to (re-)retrieve the query handle.

You could probably also use the PositionChanged event, but it does not fire at initialization (it seems) and I don't think it covers lifecycle events, like delete.

Posted by jmls on 04-Dec-2008 12:35

How, then, would I get the list of selected rows to match with the rows from the query if multiple-selection is enabled on the grid ?

Posted by Håvard Danielsen on 04-Dec-2008 14:36

The following should work:

1. Add a collection or temp-table to keep track of the current selected records. Make sure you have an integer key in addition to the info you need to identify the record(s) in ABL.

2. Use the BindingSource's CurrentChanged event to store the ABL identification info (rowids,keys..) as well as the row's ordinal position, which you can get from the ultragrid:ActiveRow:index.

3. Use the UltraGrid's AfterSelectChange event to keep the collection/temp-table synchronized with the actual selected rows using something like this:

def var iLoop as int no-undo.

def var selectedindex as int extent no-undo.

extent(selectedindex) = ultragrid1:selected:rows:count.

do iLoop = 0 to ultragrid1:selected:rows:count - 1:

     selectedindex = ultragrid1:selected:rows:index.

end.

foreach:

for each tt:

  do i = 1 to extent(selectedindex):

    if selectedindex = tt.key then

        next foreach.

  end.

  delete tt.

end.

4. use the collection/temp-table to find/position ABL data for the desired operation.

I'm sure there is lot of room for improvement here (and there could very well be logical errors in the looping/indexing.)

Some considerations:

- it is possible that you can do all of this in the AfterSelectChange event. I assume the last selected record is available there and that the CurrentChanged might not be needed. On the other hand, it might be safer/better to use CurrentChanged, which is dedicated to keep track of the current state.

- I think one will find that there is a general need for a findOrdinalRow/setPosition method in the data service/access for many purposes. The bindingsource deals with currency for the visual objects, so I think you need an additional component for operations that should not reposition the UI component. In the simplest form this is just the actual ABL query and the method is the ABL reposition-to-row. (I would most definitely wrap it in a class though)

This could make it possible to do this without the collection/temp-table.

Minor edits by:

Havard Danielsen

This thread is closed