Паскаль передает список из основной формы в немодальную форму

У меня есть список в моей основной форме, и я хочу, чтобы другая немодальная форма могла добавлять вещи. Как передать список в немодальную форму? Форма, которую я хочу изменить, отображается MainForm при нажатии кнопки, только с помощью Form.Show.

Я также должен уточнить, что я хочу, чтобы форма не использовала основную форму, чтобы избежать циклических ссылок.


person wentimo    schedule 10.04.2012    source источник
comment
** Я также должен уточнить, что я хочу, чтобы форма не использовала основную форму, чтобы избежать циклических ссылок.   -  person wentimo    schedule 10.04.2012


Ответы (3)


Самым простым и лучшим способом было бы добавить метод в принимающую форму, то есть форму с ListView, которая говорит «AddThingsToListView», и принять то, что вы хотите добавить (вероятно, TListItem?)

Таким образом, вы можете позвонить

MyMainForm.AddThingsToListView(ANewListItem);

откуда угодно.

Другими словами, не передавайте представление списка в немодальную форму; вместо этого сделайте так, чтобы основная форма могла принимать дополнения к своему списковому представлению.

person Nick Hodges    schedule 10.04.2012
comment
Это не работает. Вы не можете передать ANewListItem, так как вам нужно иметь само представление списка, чтобы создать новый элемент. В частности, вам нужно позвонить TListItems.Add или одному из его друзей. - person David Heffernan; 10.04.2012

Примечание. Вопрос изначально был помечен как Delphi. Я не знаком с FPC/Lazarus, поэтому некоторые детали ниже могут быть неточными, но концепции по-прежнему действительны.


Я предполагаю, что у вас есть глобальная переменная, представляющая основную форму, названную MainForm ради аргумента. Самый быстрый и простой подход — просто использовать MainForm.ListView, чтобы ваша другая форма ссылалась на представление списка основной формы.

Мне не очень нравится этот подход, поскольку он означает, что другая форма зависит от реализации основной формы.


В качестве альтернативы вы можете передать ссылку на представление списка в другую форму. Например, вы можете добавить процедуру SetListView в другую форму:

type
  TMyOtherForm = class(TForm)
  private
    FListView: TListView;
  public
    procedure SetListView(Value: TListView);
  end;
.....
procedure TMyOtherForm.SetListView(Value: TListView);
begin
  FListView := Value;
end;

Затем в основной форме, возможно, в обработчике событий OnCreate для основной формы, вы можете вызвать этот метод:

procedure TMainForm.FormCreate(Sender: TObject);
begin
  MyOtherForm.SetListView(ListView);
end;

Это на самом деле не намного лучше, чем первое предложение. Другая форма по-прежнему зависит от реализации основной формы, хотя, возможно, в меньшей степени.


Если вы хотите, чтобы две формы были еще менее связаны, то основная форма может предоставить метод, который принимает дополнения к списку:

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;

В вашем другом блоке форм вы добавляете основной блок формы в предложение использования в разделе реализации. Это позволяет вам получить доступ к глобальной переменной MainForm, и вы можете вызвать

MainForm.AddToList(Name, Time);

Этот подход, на мой взгляд, является лучшим, потому что он позволяет основной форме сохранять свою реализацию списка приватной для себя.


Вы заявляете в комментарии, что хотите избежать любых циклических ссылок из-за предложений uses. Это легко организовать, поскольку ни одно из вышеперечисленных не требует изменений в предложении uses из раздела интерфейса из двух рассматриваемых модулей.

person David Heffernan    schedule 10.04.2012
comment
Ваш третий подход похож на то, что я хотел бы сделать. Где именно вы бы объявили эту процедуру? Это публичные объявления основной формы? а в другой форме вы бы просто сделали TMainForm.AddToList() без необходимости использовать TMainform? - person wentimo; 10.04.2012
comment
Да, это должно быть общедоступным в TMainForm. Вы добавляете свой основной модуль формы в предложение использования раздела реализации в другом модуле. Затем вы делаете MainForm.AddToList. Не пытайтесь TMainForm.AddToList. Это не сработает. - person David Heffernan; 10.04.2012
comment
Видимо у меня на самом деле нет глобальной переменной для mainform. Где бы я объявил свою основную форму глобальной? - person wentimo; 10.04.2012
comment
@wentime Это необычно. Обычное приложение Delphi добавляет это для вас по умолчанию. .dpr обычно создает основную форму и назначает глобальную переменную, объявленную в разделе интерфейса модуля вашей основной формы. Вы должны позвонить Application.CreateForm, чтобы сделать это где-нибудь? Где вы это делаете и что вы делаете со ссылкой, которую вы передаете Application.CreateForm? - person David Heffernan; 10.04.2012
comment
Я использую Lazarus и нигде не вижу вызова CreateForm в коде для unit1. Я сделал ошибку при создании этого модуля? - person wentimo; 11.04.2012
comment
Согласно вопросу, вы используете Delphi!! В любом случае, я мало что знаю о Lazarus и FPC. Вызов Application.CreateForm обычно находится в файле .dpr. - person David Heffernan; 11.04.2012
comment
Это во многом объяснило бы мое замешательство, я хотел поместить туда паскаль! - person wentimo; 11.04.2012
comment
Концепции, рассмотренные в моем ответе, по-прежнему применимы к FPC/Lazarus, хотя я предполагаю, что реализация представления списка может несколько отличаться. - person David Heffernan; 11.04.2012
comment
Application.CreateForm находится в файле *.lpr проекта и имеет тот же смысл, что и в Delphi. - person TLama; 11.04.2012
comment
Итак, я попробовал ваш первый метод и получил следующую ошибку: unit1.pas(50,32) В методах класса могут быть доступны только методы класса, свойства класса и переменные класса. Это происходит в MyOtherForm.SetListView(ListView); вызов - person wentimo; 11.04.2012
comment
Сообщение об ошибке говорит вам ответ. Вы вызываете это из метода класса. Вам нужно вызвать из метода экземпляра. - person David Heffernan; 11.04.2012

Что я делаю: для такого рода ситуаций: я обычно объявляю модуль данных и помещаю большую часть кода, который не вписывается в библиотечные модули без графического интерфейса пользователя, в модуль данных. Модуль данных может ссылаться на формы и наоборот, но ни одна из форм не ссылается друг на друга.

В этом примере ваша форма Form2 может использовать DataModule, и вы можете сделать следующее:

  1. Имейте глобальную ссылку на ListView MainForm в модуле данных и используйте ее из своей формы.
  2. Имейте функцию/класс в модуле данных, который позволяет вам обновлять список и вызывать его из вашей формы.

В любом случае, ваша форма должна знать только о модуле данных, а модуль данных сделает все остальное. Вы можете добавлять/удалять/изменять формы, и обычно вам нужно только обновить DM.

person Noah    schedule 13.08.2012