问题
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.
回答1:
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
MyMainForm.AddThingsToListView(ANewListItem);
from anywhere.
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.
回答2:
Note: 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.
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.
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.
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
MainForm.AddToList(Name, Time);
This approach is the best in my view because it allows the main form to keep its list implementation private to itself.
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.
回答3:
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:
- Have a global reference to the MainForm's ListView in the datamodule, and use that from your form.
- Have a function/class in the datamodule that lets you update the list, and call that from your form.
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.
来源:https://stackoverflow.com/questions/10095001/pascal-passing-a-listview-from-mainform-to-a-nonmodal-form