delphi 7: How to fill a combobox from object Tcollection? - delphi

I want to know if it is possible in delphi to populate a combobox component from object Tcollection.
somme codes:
// My product list
procedure TfoMain.InitForm;
begin
FListProduct := TListeDispoProduit.Create(TProduct);
with (FListProduct ) do
begin
with TProduct(Add) do
begin
Name := 'Product 01';
CIP := 'A001';
StockQty := 3;
end;
with TProduct(Add) do
begin
Name := 'Product 02';
CIP := 'A002';
StockQty := 5;
end;
end;
// need to fill a combobox (name's cbxListProduct)
procedure TfoMain.fFillCbxFromProductList(aProductList: FListProduct);
begin
// I don't know how to do this follow
foMain.cbxListProduct.Items.Add()
end;
thank you.

Something like this (change combobox and collection names to reflect your case):
for i := 0 to Collection.Count-1 do
myComboBox.Items.Add(TProduct(Collection.Items[i]).Name);
And by the way, you don't need that "foMain" in
foMain.cbxListProduct.Items.Add()
It's enough to write
cbxListProduct.Items.Add()
When you're inside of TfoMain's procedure, TfoMain's contents is accessible by default.

In newer Delphis you can do
for item in collection do
myComboBox.Items.Add(TProduct(item).Name)

Related

Delphi create dxTileBarItem runtime

i used Delphi XE7 and DevExpress component, i need to create dxTileBarItem at runtime and add this to my dxTileBar but i cant.
var
//Tile4:TdxTileControlItem;
Tile4:TdxTileBarItem;
begin
Tile4 := TdxTileBarItem.Create(dxTileBar1);
Tile4.Name := 'Tile4';
Tile4.GroupIndex := 0;
Tile4.IndexInGroup := 3;
what is my mistake?
then i want to store a form object in manually created dxTileItem and call each from on OnTileClick such as ListBox, what do i should?
You can use the CreateItem method, for example:
var
MyTile: TdxTileBarItem;
begin
MyTile := dxTileBar1.CreateItem(tbisRegular);
MyTile.Name := 'My Tile';
...
end;
Or you can follow quite common pattern used by Delphi controls, add the item to the control's Items collection, for example:
var
MyTile: TdxTileBarItem;
begin
dxTileBar1.BeginUpdate;
try
MyTile := TdxTileBarItem(dxTileBar1.Items.Add);
MyTile.Name := 'My Tile';
...
finally
dxTileBar1.EndUpdate;
end;
MyTile.MakeVisible;
end;

Load database field of all records into ListView Item Detail Object

Using Delphi XE8 I'm currently testing functionality with Firemonkey TListViews.
One thing I'm trying to do is to load a field of all records from a TFDMemtable component into a Listview Item, specifically into the DetailObject of the ListView Item.
For example, I have 3 records in a table (db field is called 'Name'):
Record 1 = Name 1
Record 2 = Name 2
Record 3 = Name 3
There is only 1 DetailObject property per ListView Item so my question is, would I be able to add all of the fields (Name 1, Name 2, Name 3) into that one DetailObject?
Below is what I've attempted so far but no luck. Not 100% sure what I need to do.
procedure MainForm.BuildList;
var LItem : TListViewItem;
begin
ListView1.BeginUpdate;
try
ListView1.CLearItems;
LItem := ListView1.Items.Add;
LItem.Objects.DetailObject.Visible := True;
with memtable do
begin
while not eof do
begin
LItem.Detail := FieldByName('Name').AsString;
end;
end;
finally
ListView1.EndUpdate;
end;
end;
I'm sorry if this isn't clear enough, please let me know.
Any help would be great.
I think I should warn you that before seeing your q, I'd never done anything with FMX ListViews and Master/Detail datasets. The Following is a little rough around the edges, and the layout isn't ideal, but it shows one way to populate a ListView from Master + Detail datasets. I have no idea whether there are better ways. Personally, I would see if I could use Live Bindings to do the job.
procedure TMasterDetailForm.BuildList;
var
LItem : TListViewItem;
DetailItem : TListViewItem;
ListItemText : TListItemText;
DetailIndex : Integer;
begin
ListView1.BeginUpdate;
ListView1.ItemAppearanceObjects.ItemEditObjects.Text.TextVertAlign := TTextAlign.Leading; // The default
// seems to be `Center`, whereas we want the Master field name to be at the top of the item
try
ListView1.Items.Clear; //Items;
Master.First;
while not Master.eof do begin
LItem := ListView1.Items.Add;
LItem.Text := Master.FieldByName('Name').AsString;
LItem.Height := 25;
Detail.First;
DetailIndex := 0;
while not Detail.Eof do begin
Inc(DetailIndex);
ListItemText := TListItemText.Create(LItem);
ListItemText.PlaceOffset.X := 100;
ListItemText.PlaceOffset.Y := 25 * (DetailIndex - 1);
ListItemText.TextAlign := TTextAlign.Leading;
ListItemText.Name := 'Name' + IntToStr(DetailIndex); //Detail.FieldByName('Name').AsString;
LItem.Data['Name' + IntToStr(DetailIndex)] := Detail.FieldByName('Name').AsString;
Detail.Next;
end;
LItem.Height := LItem.Height * (1 + DetailIndex);
Master.Next;
end;
finally
ListView1.EndUpdate;
end;
end;
TListItemText is one of a number of "drawable" FMX objects that can be added to do the TListViewItem. They seem to need unique names so that they can be accessed via the Names property.
FWIW, I used 2 TClientDataSets as the Master and Detail in my code.
Also FWIW, for FMX newbies like me, populating an FMX TreeView is a lot more like what you'd do in a VCL project:
procedure TMasterDetailForm.BuildTree;
var
PNode,
ChildNode : TTreeViewItem;
begin
TreeView1.BeginUpdate;
try
TreeView1.Clear;
Master.First;
while not Master.eof do begin
PNode := TTreeViewItem.Create(TreeView1);
TreeView1.AddObject(PNode);
PNode.Text := Master.FieldByName('Name').AsString;
Detail.First;
while not Detail.Eof do begin
ChildNode := TTreeViewItem.Create(TreeView1);
ChildNode.Text := Detail.FieldByName('Name').AsString;
PNode.AddObject(ChildNode);
Detail.Next;
end;
Master.Next;
end;
finally
TreeView1.EndUpdate;
end;
end;
Btw, in your code you should have been calling
memtable.Next;
in your while not eof loop, and memtable.First immediately before the loop.

How Add pickup list to DBGrid at run time?

i have a DBGrid and it is linked to client dataset when i assign a SQLQuery at run time
the DBGrid automatically assigns no of column. What i need is when DBGrid automatically assign columns i need to set one of those columns to assign a picklist.
can anyone help me?
the following procedure calls in the forms on show event. the form contains DataSource, ClientDataSet, SQLViewQuery (TSQLQuery), DatasetProvider and DBGridDetails (TDBGrid).
procedure TViewDetailsForm.ViewPendingAndReturnCheques;
var I : Integer;
slPickList:TStringList;
begin
slPickList := TStringList.Create;
slPickList.Add('Pending');
slPickList.Add('Returned');
slPickList.Add('Passed');
SQL := 'SELECT a.CHEQUE_NO, a.BANK, a.CHEQUE_DATE, a.AMOUNT,a.STATUS FROM CHEQUES a';
//refreshisng the DBGrid
SQLViewQuery.SQL.Clear;
SQLViewQuery.SQL.Add(SQL);
ClientDataSet.Active := false;
ClientDataSet.Active := true;
DBGridDetails.Columns[0].Width := _Block;
DBGridDetails.Columns[1].Width := _Block;
DBGridDetails.Columns[2].Width := _Block;
DBGridDetails.Columns[3].Width := _Block;
DBGridDetails.Columns[4].Width := _Block;
for I := 0 to DBGridDetails.Columns.Count - 1 do
begin
if DBGridDetails.Columns[I].FieldName = 'STATUS' then
begin
DBGridDetails.Columns[i].ButtonStyle := cbsAuto;
DBGridDetails.Columns[I].PickList := slPickList;
end;
end;
Show;
end;
Here's a sample app I just created in Delphi 2007 that demonstrates how to accomplish this. Here's all I did to set it up:
Click File->New-VCL Forms Application from the IDE's main menu.
Drop a TClientDataSet, a TDataSource, and a TDBGrid on the form.
Click on the form, and then use the Object Inspector to create a new OnCreate event handler. Add the following code:
procedure TForm1.FormCreate(Sender: TObject);
var
SL: TStringList;
begin
with ClientDataSet1 do
begin
FieldDefs.Clear;
FieldDefs.Add('OrderNo', ftInteger);
FieldDefs.Add('Status', ftString, 10);
CreateDataSet;
end;
ClientDataSet1.Active := True;
// Connect a datasource to the CDS
DataSource1.DataSet := ClientDataSet1;
// Connect the grid to that datasource to create the columns.
DBGrid1.DataSource := DataSource1;
// Create the picklist for the second column (Status)
SL := TStringList.Create;
try
SL.Add('Pending');
SL.Add('Returned');
SL.Add('Passed');
DBGrid1.Columns[1].ButtonStyle := cbsAuto;
DBGrid1.Columns[1].PickList := SL;
finally
SL.Free;
end;
end;
Run the application, click in the Status column in the grid, and you'll see the three choices added to the PickList above.
You can assign values to the dbgrid column picklist during the run time.
Below is the code:
procedure Tfrm1.FormShow(Sender: TObject);
var
slPickList:TStringList;
I: Integer;
begin
slPickList := TStringList.Create;
slPickList.Add('Pending');
slPickList.Add('Returned');
slPickList.Add('Passed');
for I := 0 to 2 do
begin
dbgViewAxiomClaims.Columns1.PickList.add(slPickList[i]);//assigning
end;
end;
Below is the result:

delphi sorting descending

I’m trying to sort the records (in descending order ) and display the data in grid which is connected through datasource to the dataset Vw_EmpVacations
Here is the code, please tell me what I did wrong
By the way, the view is sorted descending according to start_date when I execute it in the database
Vw_EmpVacations.Active:=false;
Vw_EmpVacations.SQL.Text:='select * from Vw_EmpVacations where Branch_ID=:x and emp_id=:y and vac_id=:z order by Start_Date Desc ';
Vw_EmpVacations.Parameters[0].Value:=branch_ID;
Vw_EmpVacations.Parameters[1].Value:=emp_Id;
Vw_EmpVacations.Parameters[2].Value:=Vac_ID;
Vw_EmpVacations.Active:=true;
thank you
I will try to help you despite the fact that you are very sparse in details about your problem;-)
Please create a new VCL Forms Application - Delphi For Win32 project.
Then, replace the source of project with this code:
program SortTest;
uses
Forms, ADODB, DB, DBGrids;
var
qrySortTest: TADOQuery;
conSQL2005: TADOConnection;
dsSortTest: TDataSource;
grdTest: TDBGrid;
MainForm: TForm;
begin
Application.Initialize;
conSQL2005 := TADOConnection.Create(Application);
with conSQL2005 do
begin
Name := 'conSQL2005';
//Do not forget to change the connection string
ConnectionString :=
'Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security In' +
'fo=False;Data Source=WODZU-LAPTOP\SQL2005S';
LoginPrompt := False;
Provider := 'SQLOLEDB.1';
Connected := True;
end;
qrySortTest := TADOQuery.Create(Application);
with qrySortTest do
begin
Name := 'qrySortTest';
Connection := conSQL2005;
CursorType := ctStatic;
SQL.Clear;
SQL.Add('SELECT '#39'Kowalsky'#39' as Surname, 25 as Age');
SQL.Add('UNION');
SQL.Add('SELECT '#39'Smith'#39', 38');
SQL.Add('UNION');
SQL.Add('SELECT '#39'Jensen'#39', 11');
SQL.Add('UNION');
SQL.Add('SELECT '#39'Doe'#39', 26');
SQL.Add('UNION');
SQL.Add('SELECT '#39'Clarke'#39', 45');
SQL.Add('ORDER BY AGE DESC');
Active := True;
end;
dsSortTest := TDataSource.Create(Application);
with dsSortTest do
begin
Name := 'dsSortTest';
DataSet := qrySortTest;
end;
MainForm := TForm.Create(Application);
MainForm.Position := poScreenCenter;
grdTest := TDBGrid.Create(Application);
with grdTest do
begin
Name := 'grdTest';
Parent := MainForm;
Left := 8;
Top := 8;
Width := 320;
Height := 120;
DataSource := dsSortTest;
TabOrder := 0;
end;
MainForm.ShowModal;
Application.Run;
end.
Remember to put correct connection string to your SQL Server, otherwise it will not work.
Run the test, does it show you rows sorted by Age column in descending order? If yes, then this is the place for you to start.
Replace the qrySortTest.SQL with your parameterless query and check if it works. If not, then the problem lies in your query not in the component setup.
Hope this helps.

Is it possible to select multiple columns in Virtual Treeview?

I need to add functionality to copy a rectangular selection of nodes and columns, but I can't find any way to actually select multiple columns in a Virtual Treeview (beside toFullRowSelect).
Am I just missing something? And if not, is there a descendant out there with grid-like multicolumn select support?
So after some testing I came up with the following, thanks DiGi for the extra push. DrawSelection won't work with this solution so it needs to be disabled. Since I don't think I'll need to do this again soon I didn't write a descendant.
Set toDisableDrawSelection, toExtendedFocus and toMultiSelect to True.
Declare the following variables/properties somewhere suitable:
StartSelectedColumn: integer;
FirstSelectedColumn: integer;
LastSelectedColumn: integer;
Selecting: boolean;
Update the following events:
OnKeyDown
if (not Selecting) and (Key = VK_SHIFT) then
begin
StartSelectedColumn := vtMain.FocusedColumn;
FirstSelectedColumn := StartSelectedColumn;
LastSelectedColumn := StartSelectedColumn;
Selecting := true;
end;
OnKeyUp
if Key = VK_SHIFT then
Selecting := false;
OnFocusChanged
if Selecting then
begin
if column < StartSelectedColumn then
begin
FirstSelectedColumn := column;
LastSelectedColumn := StartSelectedColumn;
end
else if column > StartSelectedColumn then
begin
FirstSelectedColumn := StartSelectedColumn;
LastSelectedColumn := column
end
else
begin
FirstSelectedColumn := column;
LastSelectedColumn := column;
end;
end
else
begin
StartSelectedColumn := column;
FirstSelectedColumn := column;
LastSelectedColumn := column;
end;
OnBeforeCellPaint
if vtMain.Selected[node] and InRange(column, FirstSelectedColumn, LastSelectedColumn) then
begin
if vtMain.Focused then
TargetCanvas.Brush.Color := vtMain.Colors.FocusedSelectionColor
else
TargetCanvas.Brush.Color := vtMain.Colors.UnfocusedSelectionColor;
TargetCanvas.Brush.Style := bsSolid;
TargetCanvas.FillRect(CellRect);
end;
OnPaintText
if vtMain.Selected[node] and InRange(column, FirstSelectedColumn, LastSelectedColumn) then
begin
if vtMain.Focused then
TargetCanvas.Font.Color := clHighlightText
else
TargetCanvas.Font.Color := vtMain.Font.Color;
end;
You can try enable/add toGridExtensions in TreeOptions.MiscOptions. It enables free moving in columns by cursor keys, but VT still deselect column on leaving. But I'm sure that is possible to "fix" it by custom draw and remembering starting node and column.
One more tip - look at OnStateChange event, maybe you can use
procedure TSomeForm.VTreeStateChange(Sender: TBaseVirtualTree; Enter,Leave: TVirtualTreeStates);
begin
if tsDrawSelecting in Enter then
begin
// Save position
end;
end;

Resources