Тема: Как быть с событием Attribute_Change и нажатием кнопки "Отмена" на форме?

Проблема состоит в следующием.
На нашей форме есть обработчик события изменения атрибута формы, который при изменении значения атрибута изменяет другие атрибуты этого объекта и атрибуты ДРУГИХ объектов, а также, скажем, изменяет права доступа к объекту.
Получается, что если пользователь зашел на эту форму объекта и изменил значения атрибута, то запустится обработчик изменения атрибута формы и установит значения связанных атрибутов в согласованные значения.
Однако, если пользователь после изменения атрибута нажмет на кнопку "Отмена", то значение атрибута сбросится в СТАРОЕ значение, а вот все связанные атрибуты (установленные обработчиком события на форме) останутся с НОВЫМИ значениями, т.е. получаем рассогласование состояния объектов.
Как решить эту проблему?

Re: Как быть с событием Attribute_Change и нажатием кнопки "Отмена" на форме?

Для этого есть событие Object_BeforeModify  :)

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

См. руководство по программированию - программирование ТДМС на VBScript - Обработка событий.

Re: Как быть с событием Attribute_Change и нажатием кнопки "Отмена" на форме?

Этого ответа я и ожидал  :)
Но тогда возникают следующие проблемы:
1. Как мне в этом Object_BeforeModify определить, какие атрибуты объекта изменились, чтобы выполнить действия, соответствующие этим изменениям? Можно, конечно, выполнить ВСЕ действия, связанные с изменением КАЖДОГО атрибута объета, но, имхо, это не очень хорошо. Другой путь тоже извращенный - завести в Dictionary флаги, указывающие на то, какие атрибуты изменились. Но все это не решит 2-й проблемы.
2. Если нам необходимо НЕ ЗАВЕРШАЯ редактирования 1-го объекта открыть к-л связанный с ним объект, значения атрибутов которого зависят от атрибутов 1-го объекта (т.е. при изменении атрибутов 1-го объекта должны изменятся значения некоторых атрибутов 2-го объекта), то тоже получается плохо, поскольку может возникнуть такая ситуация, когда у 1-го объекта атрибут уже изменен, а у связанных с ним объектов еще нет (изменения произойдут только при нажатии на кнопку "Ок").
Я вижу 4 пути решения этих проблем:
1. При нажатии на кнопку "Отмена" производить ручной откат изменений (т.е. проставлять старые значения атрибутов так, как будто бы они были введены пользователем). Мне этот вариант не нравится, потому как с ним тоже куча проблем.
2. Прикрутить к TDMS механизм транзакций. Супер весч была бы. Но насколько это технически реализуемо - без понятия. (Может сделать механизм транзакций на основе существующиго механизма версий объектов?)
3. Собственно, "вручную" из скрипта создавать версии объектов, когда это надо.
4. Никогда не делать таких сложных связей между объектами  :)
Что скажете?

Re: Как быть с событием Attribute_Change и нажатием кнопки "Отмена" на форме?

Slava.Coder.Vrn пишет:

Я вижу 4 пути решения этих проблем:
1. При нажатии на кнопку "Отмена" производить ручной откат изменений (т.е. проставлять старые значения атрибутов так, как будто бы они были введены пользователем). Мне этот вариант не нравится, потому как с ним тоже куча проблем.
2. Прикрутить к TDMS механизм транзакций. Супер весч была бы. Но насколько это технически реализуемо - без понятия. (Может сделать механизм транзакций на основе существующиго механизма версий объектов?)
3. Собственно, "вручную" из скрипта создавать версии объектов, когда это надо.
4. Никогда не делать таких сложных связей между объектами  :)
Что скажете?

Давайте, с конца начнем  ;)

4. Истина на все времена. Так и делайте впредь.
3. Тяжеловатое решение. Объект копируется со всем содежимым  :( Но кода и глюков в таком решении намного меньше, чем в любых других.
2. Он вообще-то есть. Три метода в свойства ThisApplication (Start..., Commit..., Abort...). В конце лучше явно дать Update объекту
1. Если откат простой, то почему бы и нет? И, наоборот, если надо откатить до определенной точки изучая логические связи - то придется руками.

Выбирайте тот способ, который вам кажется наиболее правильным в конкретном случае. Это единственный верный совет во всем моем постинге   :P

Re: Как быть с событием Attribute_Change и нажатием кнопки "Отмена" на форме?

Три метода в свойства ThisApplication (Start..., Commit..., Abort...).

В хелпе ничего об этом нет!
Т.е. я могу при открытии диалога редактирования объекта сказать Start, а при закрытии окна, соответственно либо Commit, либо Abort? И во 2-м случае система примет состояние, в котором она было до открытия диалога?

Re: Как быть с событием Attribute_Change и нажатием кнопки "Отмена" на форме?

Slava.Coder.Vrn пишет:

В хелпе ничего об этом нет!
Т.е. я могу при открытии диалога редактирования объекта сказать Start, а при закрытии окна, соответственно либо Commit, либо Abort? И во 2-м случае система примет состояние, в котором она было до открытия диалога?

Сильно сомневаюсь, что все так просто. Соединение пользовательского и программного интерфейса глючит во всех виденных мной системах  :D Тестируйте. Ну и поделитесь с нами результатами

Re: Как быть с событием Attribute_Change и нажатием кнопки "Отмена" на форме?

Поскольку в хелпе ничего нет про транзакции, мне хотелось бы узнать, как этот механизм должен работать  :)
Есть какая-нить рабочая документация по поводу транзакций в TDMS? А то что мне тестировать-то?  :)

Re: Как быть с событием Attribute_Change и нажатием кнопки "Отмена" на форме?

Slava.Coder.Vrn пишет:

Поскольку в хелпе ничего нет про транзакции, мне хотелось бы узнать, как этот механизм должен работать  :)
Есть какая-нить рабочая документация по поводу транзакций в TDMS? А то что мне тестировать-то?  :)

Программный мехнизм довольно новый. Ничего конкретного нет - руководствуйтесь логикой

Re: Как быть с событием Attribute_Change и нажатием кнопки "Отмена" на форме?

И еще раз о наболевшем!  :)
Примерно та же ситуация. Зашел пользователь посмотреть табличку в определенном объекте на форме. Потыкал строки, потыкал разные вкладки. И нажал кнопку "Отмена" ну или крестик. А ему пишет: "Объект был изменен. Сохранить изменения?" Естетсвенно вижу эти недоумевающие глаза пользователя. Или допустим зашел редактировать объект. Из списка выбрал другое значение атрибута. Потом передумал и вернул назад ИЛИ! передумав вносить изменения тыкнул естественно "Отмена" или "крестик", потому как еслиб хотел внести изменения нажал бы ОК. Но ему всеравно будет выдано сообщение об изменении. Ну и как быть?

Re: Как быть с событием Attribute_Change и нажатием кнопки "Отмена" на форме?

Shoorup пишет:

И еще раз о наболевшем!  :)
Примерно та же ситуация. Зашел пользователь посмотреть табличку в определенном объекте на форме. Потыкал строки, потыкал разные вкладки. И нажал кнопку "Отмена" ну или крестик. А ему пишет: "Объект был изменен. Сохранить изменения?" Естетсвенно вижу эти недоумевающие глаза пользователя. Или допустим зашел редактировать объект. Из списка выбрал другое значение атрибута. Потом передумал и вернул назад ИЛИ! передумав вносить изменения тыкнул естественно "Отмена" или "крестик", потому как еслиб хотел внести изменения нажал бы ОК. Но ему всеравно будет выдано сообщение об изменении. Ну и как быть?

Это типа последнее китайское предупреждение. Наверно вы правы, и далеко не всегда это требуется. Попробуем решить вопрос добавлением свойства к... к чему бы его добавить?

(изменено: Shoorup, 10 ноября 2015г. 12:19:18)

Re: Как быть с событием Attribute_Change и нажатием кнопки "Отмена" на форме?

McZag пишет:

Это типа последнее китайское предупреждение. Наверно вы правы, и далеко не всегда это требуется. Попробуем решить вопрос добавлением свойства к... к чему бы его добавить?

Требуется оно если например я внес изменения и нажал крестик (нечаянно например), но это согласитесь крайне редко бывает...
В моем случае у меня есть атрибут у объекта который используется как буфер при отображении на форме. Т.е. мне не важно пустой он или заполнен чем-то. Он при просмотре формы меняет свое содержимое. Так вот как бы проверить перед закрытием объекта что если менялся только этот атрибут то закрыть и не выдавать сообщений об изменении объекта. А если менялись другие атрибуты этого объекта то ругнуться.

p.s. "Трудно быть перфекционистом"  :) Знаю, что в моем случае что бы пользователь не нажал все хорошо. Но согласитесь каждый раз тыкать лишний раз по кнопке в сообщении... зачем?
p.p.s. Может добавить птичку к "Объект" "Не выдавать предупреждение об изменении". Например для важных объектов пусть бы выдавало сообщение. А в большинстве случаев это сообщение не нужно. А если и нужно то можно в том же BeforeClose написать MsgBox что-то типа "Вы точно уверены? Хорошо подумали?"
Как быть с событием Attribute_Change и нажатием кнопки "Отмена" на форме?

Re: Как быть с событием Attribute_Change и нажатием кнопки "Отмена" на форме?

Столкнулся ровно с такой же проблемой как и в первом посте.

В моем случае это атрибут "номер объекта". Куча вложенных объектов которые копируют из родительского атрибута или копируют с добавлением чего-то там.

Объект 1 с атрибутом "номер объекта"
Объект 2 с атрибутом "номер объекта" + "123"
Объект 3 с атрибутом "номер объекта" + "456." + атрибут 7
и т.д.
И в один прекрасный день наступает ситуация когда надо изменить атрибут (ошибка закралась) от которого все копировалось:) и понеслось... ну допустим скриптик то я накидаю чтобы пробежался по всем атрибутам. Но тут проблема кнопки "отмена" появляется.

Но я еще про другое хотел сказать. А нельзя ли сделать птичку у объекта или атрибута, чтобы если значение атрибута штатно копируется от родителя то оно и синхронизировалось при изменении значения атрибута родителя? ну или спрашивало...

А вот насчет алгоритма замены, я думаю, что это не должно быть событие изменения атрибута. Думаю лучше сделать команду где пользователь осознанно будет изменять корневой атрибут и понимать что будет произведена замена значений в составе

Re: Как быть с событием Attribute_Change и нажатием кнопки "Отмена" на форме?

Shoorup пишет:

Столкнулся ровно с такой же проблемой как и в первом посте.

В моем случае это атрибут "номер объекта". Куча вложенных объектов которые копируют из родительского атрибута или копируют с добавлением чего-то там.

Объект 1 с атрибутом "номер объекта"
Объект 2 с атрибутом "номер объекта" + "123"
Объект 3 с атрибутом "номер объекта" + "456." + атрибут 7
и т.д.
И в один прекрасный день наступает ситуация когда надо изменить атрибут (ошибка закралась) от которого все копировалось:) и понеслось... ну допустим скриптик то я накидаю чтобы пробежался по всем атрибутам. Но тут проблема кнопки "отмена" появляется.

Но я еще про другое хотел сказать. А нельзя ли сделать птичку у объекта или атрибута, чтобы если значение атрибута штатно копируется от родителя то оно и синхронизировалось при изменении значения атрибута родителя? ну или спрашивало...

А вот насчет алгоритма замены, я думаю, что это не должно быть событие изменения атрибута. Думаю лучше сделать команду где пользователь осознанно будет изменять корневой атрибут и понимать что будет произведена замена значений в составе

1. Копировать значение с родителя можно, если в значение по умолчанию вставить {.Имя_родителя}
2. Откатить всю операцию можно завернув ее  в транзакцию

Re: Как быть с событием Attribute_Change и нажатием кнопки "Отмена" на форме?

По первому пункту не прокатит в моем случае, потому как строка алгоритмом формируется, а не просто {.Имя_родителя} + {attr} + "string"
А по второму пункту можно подробней? Где можно почитать?

Re: Как быть с событием Attribute_Change и нажатием кнопки "Отмена" на форме?

Shoorup пишет:

По первому пункту не прокатит в моем случае, потому как строка алгоритмом формируется, а не просто {.Имя_родителя} + {attr} + "string"
А по второму пункту можно подробней? Где можно почитать?

В справочном руководстве  :)

Вот пример кода оттуда

Sub ChangeStatus(ObjCollection, NewStatusName)

    'Открытие транзакции
     ThisApplication.StartTransaction

    'Блок каскадных изменений    
     For Each obj In ObjCollection

           Obj.Permissions = SysAdminPermissions

           For Each child In obj.ContentAll

                'Если закомментировать след. строку кода, скорее всего это вызовет ошибку -
                ' у рядового пользователя могут отсутствовать права на смену статуса.
                ' Тогда "сработает" перехвать ошибки в OnScriptError, и произведенные
                ' изменения будут отменены
                child.Permissions = SysAdminPermissions

                child.StatusName = NewStatusName
           Next      

           Obj.StatusName = NewStatusName
     Next      



    'Нормальное завершение транзакции
    ThisApplication.CommitTransaction 
End Sub

'=================================================
'Если где-то произошла ошибка, перехватываем ее
 Sub OnScriptError(ScriptDescription, Object, Line, Char, ErrorDescription, Cancel)

    'Если на момент ошибки транзакция была открыта, откатываем 
    If ThisApplication.IsActiveTransaction Then ThisApplication.AbortTransaction
End Sub