Курс молодого самурая: Управляем сабформой

Как известно, каждая форма может иметь не более одного источника данных. И для того, что бы можно было вывести на экран данные сразу из двух таблиц, зачастую используют сабформу (SubForm) .
Сабформа является отдельной формой, обычно списочной, которая вызывается другой формой в процессе работы. Выбор сабформы осуществляется при помощи свойства SubFormID элемента «сабформа». А связь формы и сабформы осуществляется посредством свойства SubFormLink. Стандартным примером такой связи служит Заказ Продажи (см. Рис. 1). Заметим, что при вставке новой строки в сабфому, в рамках нашего примера, номер документа в строке присваивается автоматически именно из-за указанного свойства.

Dynamics NAV (Navision) Дизайнер форм
Рис. 1 Свойство сабформы, отвечающее за связь данных.

Далее рассмотрим вопрос передачи данных из формы в сабформу и наоборот. Так как эти две формы являются различными хоть и зависимыми они не имеют прямого доступа к данным друг друга. Однако, если мы дадим имя сабформе (см. часть первую: Управляем Формой), то получим доступ, как к ее параметрам, так и к функциям.
Соответственно, написав функции SetValue и GetValue на сабформе, мы сможем передавать на нее данные из формы. Таким образом, при наступлении некого события на форме мы тут же можем передать «сигнал» о нем на сабформу. Если на сабформу были переданы данные, которые должны повлиять на отображаемую информацию, то следует обновить сабформу. Для этого используется вызов:
CurrForm.MySubForm.FORM.Update.
Причем функцию Update придется сделать самостоятельно. Заметим, что не стоит путать ее с вызовом CurrForm.MySubForm.UPDATE.

Наиболее интересен случай обработки формой события на сабформе. Несмотря на то, что сейчас будет рассказано о двух способах реализации такой обработки, настоятельно рекомендуется избегать таких ситуаций!
Итак, способ первый, пожалуй, самый распространенный:
Используется свойство TimerInterval и триггер OnTimer формы (см. Часть первая: Управляем формой.). И выгляди примерно так:

Form - OnTimer()   
 
IF OldValue = GetValue THEN   
 
EXIT;   
 
//код, который запускает некую процедуру по событию на сабформе.   
 
…..

Основным минусом такого способа является трудность отладки формы с таким триггером.

Второй способ не является стандартным и работает через XML 4.0. DOM.
Суть метода заключается в том, что вызов функции XMLDoc.LoadXML запускает триггер OnreadyStateChanged вне зависимости в каких объектах они находятся. Т.е. нам надо объявить переменную на форме, а затем передать на сабформу и ждать события. Пример кода представлен ниже.

OBJECT Form 50000 MyForm   
 
{   
 
OBJECT-PROPERTIES   
 
{   
 
Date=09-11-30;   
 
Time=20:14:19;   
 
Modified=Yes;   
 
Version List=;   
 
}   
 
PROPERTIES   
 
{   
 
Width=8000;   
 
Height=4840;   
 
OnOpenForm=BEGIN   
 
CREATE(XmlDoc);   
 
CurrForm.SubForm.FORM.SetXmlDoc(XmlDoc);   
 
END;OnCloseForm=BEGIN   
 
CLEAR(XmlDoc);   
 
END;   
 
}   
 
CONTROLS   
 
{   
 
{ 1000000000;TextBox;330 ;220 ;4290 ;440 ;Editable=No;   
 
SourceExpr=TextVar }   
 
{ 1000000001;SubForm;220 ;880 ;7480 ;2310 ;Name=SubForm;   
 
SubFormID=Form50001 }   
 
}   
 
CODE   
 
{   
 
VAR   
 
TextVar@1000000000 : Text[50];   
 
XmlDoc@1000000001 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 4.0:{88D969C0-F192-11D4-A65F-0040963251E5}:'Microsoft XML, v4.0'.DOMDocument40" WITHEVENTS;   
 
EVENT XmlDoc@1000000001::ondataavailable@198();   
 
BEGIN   
 
END;   
 
EVENT XmlDoc@1000000001::onreadystatechange@-609();   
 
BEGIN   
 
IF (XmlDoc.readyState = 4) THEN BEGIN   
 
  //код который обрабатывает событие на сабформе   
 
END;   
 
END;   
 
BEGIN   
 
END.   
 
}   
 
}   
 
OBJECT Form 50001 MySubForm   
 
{   
 
OBJECT-PROPERTIES   
 
{   
 
Date=09-11-30;   
 
Time=20:35:51;   
 
Modified=Yes;   
 
Version List=;   
 
}   
 
PROPERTIES   
 
{   
 
Width=8030;   
 
Height=2420;   
 
}   
 
CONTROLS   
 
{   
 
{ 1000000000;TextBox;220 ;220 ;4180 ;440 ;SourceExpr=TextVar1;   
 
OnAfterValidate=BEGIN   
 
Fire ();   
 
END;   
 
}   
 
{ 1000000001;TextBox;220 ;770 ;4180 ;440 ;SourceExpr=TextVar2 }   
 
}   
 
CODE   
 
{   
 
VAR   
 
TextVar1@1000000000 : Text[50];   
 
TextVar2@1000000002 : Text[50];   
 
XmlDoc@1000000001 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 4.0:{88D969C0-F192-11D4-A65F-0040963251E5}:'Microsoft XML, v4.0'.DOMDocument40";   
 
PROCEDURE SetXmlDoc@1000000000(pXmlDoc@1000000000 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 4.0:{88D969C0-F192-11D4-A65F-0040963251E5}:'Microsoft XML, v4.0'.DOMDocument40");   
 
BEGIN   
 
XmlDoc := pXmlDoc;   
 
END;   
 
PROCEDURE Fire@1000000004();   
 
BEGIN   
 
XmlDoc.loadXML('<root></root>');   
 
END;   
 
PROCEDURE GetText@1000000001() : Text[50];   
 
BEGIN   
 
EXIT(TextVar1);   
 
END;   
 
BEGIN   
 
END.   
 
}   
 
}

Метки:



Комментариев: 2

  1. apanko пишет:

    Гениально, использовать события от внешних компонент.
    Интересно можно ли применить для этих целей очереди http://www.nav4u.ru/archives/49-ispolzovanie-microsoft-message-queue-dlya-obmena-informaciej-s-dynamics-nav-navision/

  2. xolod пишет:

    Коротко и ясно:) Сам использую эти инструменты. Надеюсь остальным пригодится)

Оставьте свой отзыв!