I have a listview in my mainform that I want another nonmodal form to be able to add things to. How would I pass the listview to the nonmodal form? The form I want to be able to modify it is shown by the MainForm on a button click, just with Form.Show.
I should also clarify that I want the form to not use the mainform to avoid circular reference.
The simplest and best way would be to add a method to the receiving form - that is, the form with the ListView on it -- that says "AddThingsToListView", and have it accept the things you want to add (Probably a TListItem?)
That way, you can then call
In other words, don't pass the list view to the non-modal form; instead, have the main form be able to accept additions to its list view.
<strong>Note:</strong> The question was originally tagged Delphi. I don't know FPC/Lazarus so some of the details may not be accurate below but the concepts are still valid.<hr>
I'm guessing that you have a global variable representing the main form, named
MainForm for the sake of argument. The quickest and simplest approach is simply to use
MainForm.ListView to let your other form refer to the main form's list view.
I'm not terribly keen on this approach since it means that the other form takes a dependency on the implementation of the main form.<hr>
As an alternative, you can pass a reference to the list view to the other form. For example you could add a
SetListView procedure to your other form:
type TMyOtherForm = class(TForm) private FListView: TListView; public procedure SetListView(Value: TListView); end; ..... procedure TMyOtherForm.SetListView(Value: TListView); begin FListView := Value; end;
Then in the main form, probably in the
OnCreate event handler for the main form, you can call this method:
procedure TMainForm.FormCreate(Sender: TObject); begin MyOtherForm.SetListView(ListView); end;
This isn't really all that much better than the first suggestion. The other form still takes a dependency on the implementation of the main form, albeit an arguably less significant dependency.<hr>
If you want to keep the two forms even less coupled then the main form could expose a method that accepts additions to the list:
procedure TMainForm.AddToList(const Name: sting; const Time: TDateTime); var Item: TListItem; begin Item := ListView.Items.Add; Item.Caption := Name; Item.SubItems.Add(DateTimeToStr(Time)); end;
The in your other forms unit you add the main form unit to the uses clause in the implementation section. That allows you access to the
MainForm global variable and you can call
This approach is the best in my view because it allows the main form to keep its list implementation private to itself.<hr>
You state in a comment that you want to avoid any circular references due to
uses clauses. That's easy to arrange since none of the above require modifications to the
uses clause from the interface section from the two units in question.
What I do: for this kind of situation: I usually declare a data module, and put most of the code that doesn't fit neatly into non-GUI library units into the Data module. The data module can refer to the forms and vice versa, but none of the forms refer to each other.
In this example, your Form2 can use the DataModule, and you can do either:<ol> <li>Have a global reference to the MainForm's ListView in the datamodule, and use that from your form.</li> <li>Have a function/class in the datamodule that lets you update the list, and call that from your form.</li> </ol>
Either way, your form only has to know about the data module, and the data module does the rest. You can add/delete/change forms, and usually you only have to update the DM.