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

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

Сценарий открытия формы редактирования со списка

Событие редактирования на списковой форме

  • Списковые формы наследуются от 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();

См. также

Межформенное взаимодействие в Web-приложениях