How to edit TcxGrid properties by code in Delphi - delphi

What the program does
I have a function that dynamically generates a table and populates it. So...
What's the problem?
The problem is that i've tried looking for a way to edit a specific column properties by code since I can't (Obviously) use the normal properties Editor in delphi, but I've haven't had any success so far.
Here's what I've tried SO far:
for I := GridOrdiniMagazzinoPadreView1.ColumnCount - 1 downto 0 do
begin
GridOrdiniMagazzinoPadreView1.Columns[I].Destroy;
end;
GridOrdiniMagazzinoPadreView1.DataController.CreateAllItems;
GridOrdiniMagazzinoPadreView1.Columns[0].PropertiesClassName := 'CheckBox';
It doesn't show the CheckBox, I know it shouldn't do anything since i didn't set the checked status and neither how to recognize the String to set it as checked or not checked. But i expected at least to see the checkBox.

You are setting the wrong classname, passing 'TcxCheckBoxProperties' will work:
GridOrdiniMagazzinoPadreView1.Columns[0].PropertiesClassName := 'TcxCheckBoxProperties';
Anyhow, I always prefer to set the PropertiesClass property, instead of the PropertiesClassName property:
uses
cxCheckBox;
...
GridOrdiniMagazzinoPadreView1.Columns[0].PropertiesClass := TcxCheckBoxProperties;

Related

What has happened to ComboBox.Sorted := True; in Delphi 10.2?

Having recently received a 'Tumbleweed' badge for my last question, I am not sure whether I should be asking any more questions, but here goes.
I am populating a TComboBox with items from a sqlite table and this works fine. In my previous version of Delphi I was able to use ComboBox1.Sorted := True; to sort the items, but this seems to have disappeared in Delphi 10.2. I can sort the items in the table by applying a query and then populate the TComboBox from the sorted table. However, for curiosities sake I would like to find out how one now sorts items in a TComboBox. I have found some references to TComboBox(Sort:Compare) but have not succeeded in getting this to work to as of yet.
Can somebody please shed some light on this - many thanks
In Firemonkey you can populate a TComboBox instance either simply with the Items property of type TStrings or you add TListBoxItem instances with the form designer. But internally always TListBoxItem for the elements is used.
To use the TComboBox.Sort you need to provide an anonymous compare-function.
This is a simple example usage of TComboBox.Sort
cbxItems.Sort(
function (pLeft, pRight: TFMXObject): Integer
var
lLeft, lRight: TListBoxItem;
begin
lLeft := TListBoxItem(pLeft);
lRight := TListBoxItem(pRight);
Result := String.Compare(lLeft.Text, lRight.Text);
end
);

FreeReport: how to format If-Then

I use FreeReport (from FastReport) and I need to implement such code:
If TOTALPAGES > 1 then Pageheader.visible = false
I do not know, where to write this code, I tried to put inside a pascal code, it not works.
And this record do not works also:
[IFF([TOTALPAGES] > 1,'PAGEHEADER.VIBLE=0')]
What is the right way to do this?
The postition to usually place code would be a the OnBeforePrint (*) event of then PageHeader band, but this won't work with <TotalPages#>
procedure PageHeader1OnBeforePrint(Sender: TfrxComponent);
begin
TfrxPageHeader(Sender).visible := (<TotalPages#> = 1);
end;
The problem with this approach is <TotalPages#> won't be evaluated at this time.
A second problem here is the showing or hiding the PageHeader might affect the count of the pages. To achieve the desired result you will have to render the report by frxreport1.PrepareReport(true);. You might do this twice, with visible PageHeader and unvisble PageHeader. Every part of a report can be accesses by frxReport1.FindObject. Make sure this is assigned before using it.
As a sidenote, another place to effect the objects on printing/preview is the OnPrint event of the frxReport component, which will be called for every object before it's rendered.
begin
frxReport1.FindObject('PageHeader1').Visible := true;
frxReport1.PrepareReport(true);
// in my test case 2 Pages
Showmessage(IntToStr(frxReport1.PreviewPages.Count));
frxReport1.ShowPreparedReport;
frxReport1.FindObject('PageHeader1').Visible := false;
frxReport1.PrepareReport(true);
// in my test case 1 Page
Showmessage(IntToStr(frxReport1.PreviewPages.Count));
frxReport1.ShowPreparedReport;
end;
The usual place implement report code:
You can try similar code inside report:
[if([PAGE#] < [TOTALPAGES], 'Ok', 'Not Ok')]

TStrings vs TStringList in TCheckListBox

In Delphi 7, I'm using a TCheckListBox. I want it to use a TStringList rather than a TStrings, so I can set Duplicates to dupIgnore, and Sorted to TRUE.
Can I just do this:
Form1 = class(TObject
CheckListBox1: TCheckListBox; // created by the IDE
end;
procedure TForm1.FormCreate
begin
CheckListBox1.Items.Free;
CheckListBox1.Items := TStringList.Create;
CheckListBox1.Items.Sorted := TRUE;
CheckListBox1.Items.Duplicates := dupIgnore;
end;
Is this safe? Any caveats or suggestions?
EDIT: Removed declaration for MyStringList and added .Items to the last two assignment lines.
EDIT 2: Trying to compile the above, it looks like I'd have to cast the two final lines like this:
TStringList(CheckListBox1.Items).Sorted := TRUE;
TStringList(CheckListBox1.Items).Duplicates := dupIgnore;
Although I might be able to get this to run, I'm asking the question because just getting it to run doesn't mean it will always run or is safe.
You don't control what class TCheckListBox uses to store its items. Assigning the Items property a value only assigns its items to the internal storage.
Also, you shouldn't call Items.Free;. TCheckListBox depends on its internal instance of TListBoxStrings.
To answer your edits in your question: Don't hard-cast the Items property to TStringList, either. The typecast is wrong (the instance exposed by Items is not a TStringList) and will only cause problems.
Edit, to suggest a workaround for what you seem to try to achieve: To keep the checklistbox sorted, you can set its Sorted property to True. To avoid duplicates, you can check the list before adding an item in code.

Some help tracking down an exception while loading a form with a SMDBGrid

I've got a form with a DB grid on it. It worked fine as a normal TDBGrid, but when I replaced it with the Scalabium TSMDBGrid, I started getting exceptions while loading the form.
Here's the problem, as far as I can track it down:
While loading the columns from the DFM, it attempts to set the Expanded property on the first column to False. This is set in the Form Designer, and can't be changed unless the column is bound to a field representing an ADT or array.
For some reason, the columns are created in the constructor with FExpanded set to true. When the reader reaches this point, it calls TColumn.SetExpanded(false), which does this:
begin
if Value <> FExpanded then
begin
Grid := GetGrid;
WasShowing := (Grid <> nil) and Grid.Columns[Grid.SelectedIndex].Showing;
...
Unfortunately, at this point Grid.SelectedIndex is -1, so I get "Exception class EListError with message 'List index out of bounds (-1)'." This is a pretty clear invariant: SelectedIndex should not be -1 when SetExpanded is called. Does anyone know why the TSMDBGrid is breaking it and what I can do to fix it?
I would try assigning the dataset/datasource properties in code, instead of designtime, just as a quick work around.
Try to recreate the column list if designer

Access Violation when assigning component property on Data Module

I'm on Delphi 2009, and my application contains a data module, which has a custom component named 'Globals' on it.
In another form in the application, I'm trying to change a published property (a string) on the Globals component:
dm.Globals.qhProject := _ProjectName.Text; //always gives access violation
The _ProjectName control is a TLabeledEdit descendant. I always get an access violation here if there's any text in the box.
However, if I manually assing a string to the property, I don't get the AV:
dm.Globals.qhProject := 'some text'; //works
Here's the declaration of the qhProject property:
FqhProject: string;
property qhProject: string read FqhProject write FqhProject;
I can't figure out why there's an AV here at all. I've tried moving the auto create order of the forms/data module around, but I always get the AV.
What am I doing wrong here?
Update:
I'm using Billenium Effects TFormContainer to switch between different forms in the application. Both forms that are involved here are in the form container. One form, TdlgSummary, contains the following:
procedure TdlgSummary.SyncVars;
begin
dm.Globals.qhProject := _ProjectName.Text
end;
The other form, TdlgFinalize, contains the following:
dlgSummary.SyncVars;
If I run SyncVars inside of dlgSummary, it works fine. If I call it from dlgFinalize, I get the AV. This seems to be the crux of the problem, but I can't figure out what's going wrong. Even if I switch control to dlgFinalize, dlgSummary hasn't been destroyed, because I can go back to it. Any ideas?
Looks to me like _ProjectName is nil. Try putting a breakpoint at this line and examine _ProjectName, see if it gives a valid reference or not.

Resources