Межформенное взаимодействие рассмотрено в контексте того, какие события происходят, какие методы вызываются, что конкретно проверяется и присходит при этом, какие объекты и как обрабатываются, описывается работа с кэшем форм и обращения к системе проверки полномочий, указаны возможные исключительные ситуации.
Сценарий открытия формы редактирования со списка
Событие редактирования на списковой форме
- Списковые формы наследуются от
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();