Pascal passing a listview from mainform to a nonmodal form

♀尐吖头ヾ 提交于 2019-12-11 00:44:14

问题


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:

  1. Have a global reference to the MainForm's ListView in the datamodule, and use that from your form.
  2. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!