Межформенное взаимодействие рассмотрено в контексте того, какие события происходят, какие методы вызываются, что конкретно проверяется и присходит при этом, какие объекты и как обрабатываются, описывается работа с кэшем форм и обращения к системе проверки полномочий, указаны возможные исключительные ситуации.
Сценарий открытия формы редактирования со списка
Событие редактирования на списковой форме
- Списковые формы наследуются от
BaseWinListStandardлибо отBaseWinListHierarchical. Отличаются они тем, что в первом случае на форме расположен контрол ObjectListView, а во втором случае используется ObjectHierarchicalView. Событие редактирование на форму приходит именно из одного из этих контролов. Подписывание на это событие выполняется методомprotected void prv_AttachObjectListView( ICSSoft.STORMNET.Windows.Forms.ObjectListView objectListView1 ), который вызывается из конструктора базовой списковой формы. В этом же методе происходит инициализация свойстваListControlбазовой списковой формы.

BaseWinList: Обработчик событияObjectListView.EditObjectвызывает методprotected virtual void objectListView1_EditObject(object sender, ICSSoft.STORMNET.Windows.Forms.GroupEventArgs e). Далее происходит вызовprotected virtual void prv_EditData(), а отсюдаprotected virtual void prv_EditData( ICSSoft.STORMNET.Windows.Forms.ObjectListView ol )BaseWinList.prv_EditData: берутся все выбранные объекты, если их больше одного, то задаётся вопрос о необходимости открыть на редактирование все эти объекты. В случае положительного ответа пользователя вызываетсяOnEditEvent( "", dobj, "" ), который вызывает срабатываниеEditEventна формеBaseWinList.BaseIndpdListбыла подписана на событиеEditEventсвоей зависимой формы в методеpublic virtual void Activate( object tag ). Этот метод участвует в EBSI-скрипте, по которому работает независимая списковая форма. Т.е. этот метод сработал когда списковая форма была запущена.

- В обработчике события редактирования с зависимой формы вызывается событие редактирования на независимой форме, которое используется на EBSD-диаграмме.
Получение формы-редактора
- Когда вызывается
EditEventна независимой списковой форме, включается в работу интерпретатор EBSD-скрипта. Это событие приводит к вызову методаGetEditorнезависимой списковой формы. Этот метод переопределяется в сгенерированной независимой форме. Он возвращает тип формы редактора на основании информации о редактируем объекте.
Требуется возвращать тип независимой формы, т.к. именно она является предметом работы интерпретатора скриптов.
- Получив тип формы редактирования, далее начинается работа с кэшем форм редактирования:
EditFormCache. Сначала проверяется наличие этой формы. - Если форма в кэше отсутствует, то следующим шагом скрипта будет
System.Activator.CreateInstance(editFormType)и помещение созданной формы вEditFormCache. - Если форма в кэше найдена, то для неё сразу выполняется следующий шаг сценария.
Запуск формы-редактора
- Форма-редактор запускается вызовом метода
Editнезависимой формы. - При этом, если форма была взята из кэша ранее, то этот метод вызывается без запуска нового интерпретатора скриптов и подписывания на события.
- Если форма запускается впервые, то произойдёт старт нового интерпретатора скрипта запускаемой формы. Скрипт для этой формы будет получен вызовом метода
GetScript(), который всегда переопределяется в сгенерированном коде. Кроме этого, выполняется подписка на событие сохранения (SaveEvent) и на событие отмены (CancelEvent) поднимаемой независимой формы. - Метод
Editнезависимой формы редактирования:- Происходит проверка полномочий на открытие этой формы
- Если параметр
propertynameне пустой, то происходит проверка на наличие такого свойства типаDataObjectу объекта, переданного на редактирование.- Если свойство найдено, но это свойство в объекте ==
null, то редактирование отменяется, метод завершает свою работу. - Если свойство найдено и !=
null, то будем редактировать этот мастеровой объект вместо переданного параметромdataobject - Если свойство не найдено, то продолжаем работать с объектом, переданном параметром
dataobject
- Если свойство найдено, но это свойство в объекте ==
- Если форма поднимается впервые (это определяется по отсутствию объекта данных (
DataObject) на независимой форме), то- Проверяется наличие полномочий на редактируемый объект (
FullControlилиRead). Если таких прав нет, то выдастся форма сUnauthorizedAccessExceptionи редактирование объекта на этом закончится. - Если нет права на
InsertилиUpdate, то объект откроется без блокировки - только на чтение.
- Проверяется наличие полномочий на редактируемый объект (
- Если на независимой форме объект данных (
DataObject) уже имеется и его первичный ключ совпадает с тем, что пришёл на редактирование, то происходит вызовForm.Select()и выход из метода. - Если на независимой форме объект данных (
DataObject) отсутствует, то- Показывается пустая зависимая форма, вызовом её метода
Editс пустыми параметрами - Устанавливается зависимой форме статусное сообщение загрузки
- Вызывается метод независимой формы:
PrepareDataObjectForEdit(dataobject);, который переопределён в сгенерированном коде - Копируется редактируемый объект методом
DataObject.CopyTo()и эта копия присваивается свойствуDataObjectнезависимой формы редактирования. Именно это свойство будет использовано для проверки необходимости задавать вопрос о сохранении объекта при закрытии формы. - Редактируемый объект передаётся в метод
Editзависимой формы. - Выставляется статусное сообщение на зависимой форме “Готово”.
- Метод
Editзависимой формы редактирования:- Вызывается
protected virtual void prv_Edit( Storm.DataObject dataobject, string contpath, string propertyname ), в котором присваиваетсяEditManager.DataObject, выставляетсяCaptionдля формы, в зависимости от статуса редактируемого объекта, а затем вызываетсяEditManager.Change( false );
- Вызывается
- Показывается пустая зависимая форма, вызовом её метода
- Если
DataObjectна зависимой форме (который является ссылкой наEditManager.DataObject) !=null, то вызывается событиеICSSoft.STORMNET.Windows.Forms.Desktop.GlobalWinformEvents.OnIntEditFormDataLoaded(this, EventArgs.Empty); - Вызывается метод
Show(); - Если
DataObjectна зависимой форме !=null, то вызывается событиеOnDataObjectOnFormLoaded(new EventArgs());
Сценарий сохранения объекта
BaseIndpdEdit- базовая независимая форма редактирования. В её конструкторе вызывается методGetDpdForm();, который переопределяется в сгенерированной независимой форме. Этот метод должен вернуть экземпляр зависимой формы.-
Полученная зависимая форма присваивается свойству
Editorбазовой независимой формы, и в этот момент вызывается методprivate void prv_AttachSystemEvents()в котором происходит подписка на события зависимой формы (закрытия, сохранения, отмемы и пр.).
- Форма редактирования работает по сценарию:
Событие сохранения на независимой форме редактирования.
- Первый вариант: кнопка на тулбаре. Сначала срабатывает обработчик кнопок на тулбаре, который вызывает
OnSaveEventзависимой формы. На это событие подписан обработчик в независимой формы, который сначала вызывает методprotected virtual void OnSave(SaveEventArgs e), а затем если не случилосьm_bFailedSaveи зависимая форма не находится в режиме закрытия (ClosingMode), то происходит копирование объекта данных с зависимой формы в свойствоDataObjectнезависимой формы. - Другой вариант: обработка закрытия формы через нажатие на “Х”.
- В обработчике события закрытия зависимой формы –происходит чудо– берётся объект данных, который был сохранён на независимой форме редактирования и объект данных с зависимой формы.
- Если объект данных на зависимой форме не
nullи не заблокирован, то получается массив различающихся свойств методомInformation.GetAlteredProperyNames(), включая проверку на различающиеся свойства детейлов. - Если статус объекта на зависимой форме равен
Createdили имеются различающиеся с объектом на независимой форме свойства, то в случаезависимая_форма.ClosingMode == falseвызывается методpublic virtual ICSSoft.STORMNET.UI.DialogResult PromtUserForActionAtClose();зависимой формы редактирования. PromtUserForActionAtClose()показываетMessageBoxсMessageBoxButtons.YesNoCancel.- Соответственно ответам пользователя срабатывают события независимой формы редактирования:
Yes:OnSave();e.Cancel = m_bFailedSave;; т.е. в переопределённомOnSaveвы можете поставитьm_bFailedSave = true;и закрытие формы не произойдёт.No:OnCancel();, затем вызываетсяprotected virtual void prv_ApplyChanges(ICSSoft.STORMNET.DataObject dataobject, ICSSoft.STORMNET.DataObject dataobjectcopy)для отката изменений, которые были произведены в объекте, редактируемом на зависимой форме.Cancel: происходит простая отмена закрытия формы:e.Cancel = true;
- Если изменённых свойств нет и статус не
Created, то вызываетсяOnCancel(); e.Cancel = false; - Если отмена закрытия не случилась, то в конце работы метода происходит сброс блокировки для данного объекта.
- Первый вариант: кнопка на тулбаре. Сначала срабатывает обработчик кнопок на тулбаре, который вызывает
- Метод
OnSaveнезависимой формы редактирования:- Выполняется проверка
NotNullсвойств редактируемого объекта данных.- Если есть незаполненные свойства, то вызывается метод
public virtual void DisplayNullPropertiesWarning( string[] captions )зависимой формы, выставляется флагm_bFailedSave = true;и вызывается ещё один методpublic virtual void FailedSave( Exception e )зависимой формы, выставляется статусное сообщение зависимой форме об ошибке сохранения. Выполняется возврат из функции.
- Если есть незаполненные свойства, то вызывается метод
- Если незаполненных обязательных полей нет, то выставляется флаг
m_bFailedSave = false;, ставится статусное сообщение зависимой форме о выполнении процесса сохранения, проверяется статус редактируемого на зависимой форме объекта данных. - Вызывается
SaveEventнезависимой формы редактирования - Если форма не закрывается (
ClosingMode) иm_bFailedSave != false, то зависимой форме выставляется статус готовности, иначе выставляется статус ошибки при сохранении и происходит выход из функции. - Если редактируемый объект до выполнения
SaveEventбыл в состоянииCreated, то на него ставится блокировка. - Вызывается метод
public virtual void Edit(Storm.DataObject dataobject, string contpath, string propertyname)зависимой формы редактирования. Это происходит для переинициализации формы редактора, т.к. при сохранении объект мог быть изменён в бизнес-серверах.
- Выполняется проверка
- Списковая форма в своём скрипте была подписана на событие сохранения.
- Переданный параметром события отредактированный
DataObjectпередаётся в специальный Бизнес-сервис - оболочку “вокруг” сервиса данных для обновления объекта. - В случае ошибки при сохранении произойдёт вызов метода
FailedSaveнезависимой формы редактирования - В случае успешного сохранения вызовется метод
public virtual void Edited(DataObject dataobject, string contpath, string propertyname)независимой списковой формы, который вызываетpublic virtual void Edited(Storm.DataObject dataobject, string contpath, string propertyname)зависимой формы, которая вызоветprotected virtual void prv_Edited( ICSSoft.STORMNET.DataObject dataobject ), а эта функция добавляет объект в ObjectListView на этой форме.
- Переданный параметром события отредактированный
Сценарий открытия списковой формы на лукап
-
Сценарий выбора значения мастера на лукап-форме
-
Межформенное взаимодействие в Flexberry Platform Чтобы вызвать списковую форму, в которой редактируется объект, можно использовать метод OnEdit, а получать обработанный объект в методе Edited.
Для того, чтобы поднять модальную форму можно делать, например, следующим образом:
(form as ICSSoft.STORMNET.UI.BaseIndpdList).SaveEvent += new ICSSoft.STORMNET.UI.SaveEventArgsHandler(OnReturnFromList);
(form as ICSSoft.STORMNET.UI.BaseIndpdList).Edit(dobj, "", LookUpProp, lf);
DPD_frm = (System.Windows.Forms.Form) (form as ICSSoft.STORMNET.UI.BaseIndpdList).EditInitiator;
DPD_frm.Hide();
DPD_frm.ShowDialog();
Хотя, с точки зрения технологии, правильнее будет вызывать форму на OnEdit, а в зависимой форме (той формы, которую хотим поднять), переопределить базовыйметод Edit, который выглядит так:
/// <summary>
/// Начать редактирование свойства объекта данных (фактически вызов на лукап)
/// </summary>
/// <param name="dataobject">объект данных</param>
/// <param name="contpath">некоторый путь на форме-инициаторе, для идентификации объекта, в случае, когда форма редактирует одновременно несколько объектов данных</param>
/// <param name="propertyname">имя свойства</param>
public virtual void Edit(Storm.DataObject dataobject, string contpath, string propertyname, object tag)
{m_objDataObject = dataobject;
m_sContPath = contpath;
m_sPropertyName = propertyname;
m_bLookupMode = true;objListView.Operations.Up = true;
if( tag is ICSSoft.STORMNET.FunctionalLanguage.Function && tag != null )
{objListView.LimitFunction = ( ICSSoft.STORMNET.FunctionalLanguage.Function )tag;}this.Show();
return;}
Например, вместо this.Show(); можно написать this.ShowDialog();