Buenas tardes, amigos!

Господа, прошу руку помощи в следующем, непонятном мне моменте.

Существует окно, в нём есть список и memo поле.
При инициализации окна, полю memo устанавливается свойство IsReadOnly = true;
При изменении пункта в списке (на какой то определённый) устанавливается свойство memo.IsReadOnly = false, но само поле в окне остаётся недоступным.

Где здесь собака зарыта?

С уважением
Ваш коллега.

Нравится

13 комментариев

Yegor, проверьте чему установлено свойство IsEnabled (посмотрите как визуально в свойствах элемента, так и не устанавливается ли свойство программно).
Чтобы понять в чем причина поможет реализованный Вами код либо сервисы.

Наталья, при выводе значения свойства через MessageBox указываются ожидаемые значения. Но в самом окне изменения не происходят (поле как было только для чтения (окрашено в серый цвет) так и осталось).

Код события Prepare окна

// Подразумевается
// Если пользователь принадлежит группе, и поле Dataset - StatusComplaintID равно конкретному определённому значению, то блок frame group формы становится активным для этих пользователей.
// Вывод MessageBox - true - ..., true - ...
function wnd_ComplaintEditOnPrepare(Window) {
    ...
    if ( Dataset('StatusComplaintID') == compstatAnalized && IsContactIDInUserGroup(Connector.CurrentUser.ContactID, AdmUnitSupervisorCallGroup) ) { // Специалистам ГКС 2 линия могут осуществлять доразбор рекламации
    fgComplaintAnalysis.IsEnabled = true;
    //edtAppDescription.IsEnabled = false; пытался обыграть с отключением поля, но не могу дойти до него загрузив сервис в другом файле =) (пока просто не знаю как получить доступ к полю)
    var dsApplication = dlApplication.Dataset;
    dsApplication.Open();
    dsApplication.DataFields.ItemsByName('Description').IsReadOnly = true;		
    MessageBox(dsApplication.DataFields.ItemsByName('Description').IsReadOnly + " - свойство IsReadOnly\n" + dsApplication.DataFields.ItemsByName('Description').IsEnabled + " - свойство IsEnabled");
    }	
}

Далее событие DatasetDataChange

// Подразумевается
// Если в окошке в списке выбрали Статус с конкретным значением - то снимается свойство IsReadOnly, при любом другом значении вновь устанавливается.
function ds_ComplaintOnDatasetDataChange(DataField) {
    ...
    var Name = DataField.Name;
    var Value = DataField.Value;
    ...
    switch (Name) {
    ....
    case 'StatusComplaintID':
    var dsApplication = Services.GetNewItemByUSI('ds_ApplicationToNP');
    if (Value == compstatAppInNP) {
	dsApplication.DataFields.ItemsByName('Description').IsReadOnly = false;
	MessageBox(dsApplication.DataFields.ItemsByName('Description').IsReadOnly + " - свойство IsReadOnly\n" + dsApplication.DataFields.ItemsByName('Description').IsEnabled + " - свойство IsEnabled");
    } else {
        dsApplication.DataFields.ItemsByName('Description').IsReadOnly = true;
	MessageBox(dsApplication.DataFields.ItemsByName('Description').IsReadOnly + " - свойство IsReadOnly\n" + dsApplication.DataFields.ItemsByName('Description').IsEnabled + " - свойство IsEnabled");
    }				
}

* Под Application подразумевается заявка
* Под ApplicationToNP - заявка в смежное (neighbour) подразделение
Это не приложение =)

Свойства устанавливаются, но ожидаемого эффекта в самом окне не происходит
В Dataset у данного поля checkbox "только для чтения" - снят.
Возможно я чего то не знаю, прошу подсказать =)

Егор, добрый день.

Вы, наверное, запутались в двух (соснах)свойствах - IsReadOnly и IsEnabled. Первое свойство - это свойство DataField'а датасета, второе - это свойство контрола в карточке:

myControl.DataField.IsReadOnly = true;
myControl.IsEnabled = true;

В Вашем случае:

OnPrepare(Window) {
 
 
myMemo.DataField.IsReadOnly = true;
//myMemo.IsEnabled = false;
}
 
 
DataChange(DataField) {
 
if(DataField.Name == 'myListDataField' && !IsEmptyValue(DataField.Value)) {
myMemo.DataField.IsReadOnly = false;
//myMemo.IsEnabled = true;
}

Yegor, обратите внимание:
1. Как написал Дмитрий, у DataField'а нет свойства IsEnabled. Эта запись некорректна:

dsApplication.DataFields.ItemsByName('Description').IsEnabled

2. В функции ds_ComplaintOnDatasetDataChange Вы создаете новый экземпляр датасета. Нужно обращаться к уже существующему:

var dsApplication = dlApplication.Dataset;

Про свойства контрола я тоже помню, но в данном случае я его не использовал. (По совету Натальи проверил свойство IsEnabled как раз DataField'a)

Но всё равно при изменении свойства при смене пункта списка, поле не становится доступным для редактирования (возможно надо как то обновить окно, но подобных событий я не нашёл)

Если формально то пытаюсь достигнуть следующего
К примеру
есть список с языками

  • Русский
  • Английский

и есть два поля с текстом (оба недоступны для редактирования)
При выборе из списка пункт Русский соответствующее поле с текстом становится доступным для редактирования (сразу же), аналогично при выборе другого, поле блокируется, а с другого блокировка снимается. (Может быть пример не самый лучший, но суть описывает)
Возможно ли что то подобное сделать с окном в TerraSoft?
Повторюсь что при срабатывании DataChange свойство изменяется, но эффект не наблюдается.

"Бондарь Наталия" написал:Как написал Дмитрий, у DataField'а нет свойства IsEnabled. Эта запись некорректна:
dsApplication.DataFields.ItemsByName('Description').IsEnabled

Возьму на веру (Надо тогда SDK подправить) Вот вырезка на которую ссылался.
Свойство IDataField::IsEnabled

Признак активности поля.
IDL
__property VARIANT_BOOL IsEnabled;
Описание
Содержит значение "True", если поле набора данных является активным. Иначе содержит значение "False".

Если свойство содержит значение "False", то поле не участвует в формировании запросов, и значение данного поля получить и изменить нельзя.

С новым экземпляром скорее всего причина =) только сразу вопрос дилетантский) из скрипта датасета будет виден dlApplication???

"Litvyakov Yegor Vladimirovich" написал:из скрипта датасета будет виден dlApplication

Из скрипта датасета - нет. Для получения датасета используйте запись вида:

var dsApplication= DataField.ParentDataFields.ParentDataset;

"Litvyakov Yegor Vladimirovich" написал:Возьму на веру (Надо тогда SDK подправить) Вот вырезка на которую ссылался.

Вы правы, свойство IsEnabled у DataField действительно есть, немного ошиблась.
Но отвечает не за возможность редактирования поля, а за активность поля датасета (будет ли поле участвовать в формировании запроса).

В посте №1 я писала о свойстве IsEnabled контрола.

Упс :biggrin: точно.
Да и самая главная проблема. У DataField родительский Dataset не тот который нужен.
(При изменении поля одного датасета, надо разблокировать поле другого)
В такой ситуации я до существующего нужного Dataset'a не доберусь??? Или это возможно использую функцию GetSingleItemByCode?

Егор, вы все усложняете.
На OnPrepare заблокируйте нужные Вам контролы (или датафилды, тут по желанию) одной строкой.
А на датачендже просто в условии if(DataField.Name == 'myDropDownDataField') разблокируйте его опять таки одной строкой.
Тут я писал пример

А почему не создать обработчик события OnDatasetDataChange для компонента DatasetLink карточки?
В результате Вы сможете прописать ту же логику только обращаясь к компонентам DatasetLink (в данном случае к dlApplication).

Прописал то же самое что и выше, только в событии компонента DatasetLink, как предложила Наталия

"Бондарь Наталия" написал:А почему не создать обработчик события OnDatasetDataChange для компонента DatasetLink карточки?

В данном случае как раз получается без "танцев с бубном" получить Dataset не создавая новый экземпляр.

Наталия, Дмитрий, спасибо большое за помощь! Вы мне очень помогли в решении задачи и понимании системы =) (осталось куча вопросов, но куча разрешилась :mrgreen:)

С уважением
Егор

Показать все комментарии

Buenas tardes!

Вся философия - знать то, как думает компилятор.
Уважаемые знатоки, внимание вопрос.
Поясните пожалуйста момент срабатывания события onDatasetChangeDataField(Dataset, DataField); (Событие, генерируемое при изменении активного поля записи набора данных. Активное поле набора данных определяется наличием фокуса в соответствующем визуальном элементе управления (IDataControl). При изменении фокуса генерируется данное событие.
), в чём его принципиальная особенность и отличие от onDatasetDataChange(DataField); (Событие, генерируемое при изменении значения поля набора данных.)

На сколько я понял, события наступают одновременно. Первое после изменения отдельного IDataControl, и снятия с него фокуса, второе ... после изменения Dataset('Field');. Что, подозреваю одно и тоже.

Абстракция Por examplo:
Есть форма на которой есть поле связанное с набором данных. Есть пользователь, который хочет отредактировать это поле, изменив данные и сохранив изменения в базе.

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

Буду очень благодарен за объяснение философии TerraSoft.

С уважением Ваш коллега.

Нравится

6 комментариев

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

"Litvyakov Yegor Vladimirovich" написал:второе ... после изменения Dataset('Field')

при любом изменении любого поля в наборе данных (например, ввод очередного символа в строковое/числовое поле или выбор из справочника, или исполнение Dataset('Date') = new Date(System.Now()).getVarDate())

я тоже пытался выяснить этот вопрос, хотя с другой стороны немного
философия Террасофт заключается в том, что есть объекты Window, DatasetLink (обычно зовется dlData), Control, DataField, Dataset все связи между ними описаны в SDK. Что срабатывает первое - вопрос, оставшийся открытым. Но вроде как всегда сначала срабатывает событие на Dataset'e (но не уверен)

"Андросов Дмитрий" написал:при любом изменении любого поля в наборе данных

Дмитрий, получается - когда пользователь только ввёл символ в поле редактирование, dataset уже изменил соответствующее своё поле, текущего картежа, и готов к Post() для сохранения в базе?

поле можно изменить, если Dataset в состоянии dstInsert или dstEdit см SDK
в тех же состояниях он готов к Post() опять-таки см SDK (там правда опечатка должно быть:

1. 
Если набор данных находится в состоянии добавления или редактирования записи (значение свойства IDataset::State не равно "dstInsert" или "dstEdit"), то вызывает событие IDatasetEvents::OnDatasetBeforePost. Иначе метод завершает работу. 

"Litvyakov Yegor Vladimirovich" написал:dataset уже изменил соответствующее своё поле

если Control и DataField связаны и действие не отменено где-нибудь (например в событии OnKeyPress у Control'a), то да

Огромное спасибо за пояснение, есть просвет)

Здравствуйте, коллеги!
По поводу onDatasetChangeDataField Дмитрий правильно предположил, это артефакт, и следует пользоваться событием onDatasetDataChange. Единственная разница между этими событиями - это то, что onDatasetChangeDataField не работает с BLOB полями.
По поводу вопроса, кто первый Control, DataField или Dataset сказать сложно. Обработка событий происходит в порядке подписки. Подписка выполняется ядром во время десериализации сервисов, а порядок подписки может быть разным, в зависимости от того, в какой момент устанавливается связь между объектами.
Например, для dlData может быть определен DataSet как в скрипте, так и с помощью установки соответсвующего свойства из интерфейса и т.д.

"Андрей Каспаревич" написал:По поводу вопроса, кто первый Control, DataField или Dataset сказать сложно.

Можно в обработчик каждого события впихнуть

 Log.Write(1,"текст сообщения");

и посмотреть, кто за кем.

Показать все комментарии