AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 19.06.2014, 15:40   #1  
Hyper is offline
Hyper
Участник
Соотечественники
 
163 / 29 (1) +++
Регистрация: 09.10.2003
? Enterprise Portal: OnDataChanged для поля типа utcDateTime
Столкнулся с такой проблемой в Enterprise Portal, AX 2012:

В веб-контроле используется AxBoundField, привязанное к полю типа utcDateTime. На веб-странице оно отображается как два элемента: отдельно дата (со встроенным пикером/лукапом) и отдельно время.

Задача: при изменении даты или времени автоматически произвести некие действия. Например, изменить значения других полей на странице или скрыть/отобразить какие-то элементы управления и т.п.

Проблема в том, что событие OnDataChanged (и postback) запускается только если дата или время были изменены вручную, и не запускается, если дата была выбрана мышкой с помощью лукапа. Событие OnLookup при этом также не запускается.

Естественно, AutoPostBack и UpdateOnPostBack везде, где надо, установлены в True.

Кстати, modifiedField на таблице, вроде, запускается несмотря на то, что не запускается OnDataChanged. Т.е. автоматические действия в AX выполняются, но изменения не отображаются на странице до следующего postback.

Подскажите, пожалуйста, простейший способ перехватить событие при выборе даты с помощью лукапа.
Старый 24.06.2014, 10:20   #2  
Dreadlock is offline
Dreadlock
Участник
Аватар для Dreadlock
 
298 / 224 (8) ++++++
Регистрация: 07.05.2009
Адрес: Москва
Можно добавить событие onchange в HTML'ый контрол.

У меня была ситуация, когда надо было всем полям добавить событие на изменение значения в любом поле. Я рекурсивно обходил все элементы на форме и добавлял скрипт:

X++:
private void setControlAttributes(ControlCollection collection)
{        
        foreach (Control curControl in collection)
        {
            if (curControl.GetType() == typeof(DataControlFieldCell) ||
                curControl.GetType() == typeof(TableCell))
            {
                WebControl control;
                if (curControl.GetType() == typeof(DataControlFieldCell))
                {
                    control = (DataControlFieldCell)curControl;
                }
                else
                {
                    control = (TableCell)curControl;
                }
                AttributeCollection attCollection = control.Attributes;
                attCollection.Add("onchange", "onClientChange();");
            }

            if (curControl.Controls.Count != 0)
            {
                setControlAttributes(curControl.Controls);
            }
        }
}
Сам PostBack можно сделать так:
PHP код:
<script type="text/javascript" language="javascript">                  
    function 
onClientChange() {
        
//do the postback
         
__doPostBack('__Page'''); 
    }       
</script> 
P.S. Помнится, что в IE вместо onchange применялось другое событие, но пример найти не могу
За это сообщение автора поблагодарили: trud (3), gl00mie (3).
Старый 24.06.2014, 13:30   #3  
Hyper is offline
Hyper
Участник
Соотечественники
 
163 / 29 (1) +++
Регистрация: 09.10.2003
Цитата:
Сообщение от Dreadlock Посмотреть сообщение
Можно добавить событие onchange в HTML'ый контрол.
Сам PostBack можно сделать так
Я тоже думал в этом направлении, но с другого конца: я подумывал все делать в JavaScript.

1) перекрыть onload c тем, чтобы когда страница загрузилась, добавить событие на нужный элемент INPUT
2) для того, чтобы найти элемент, к которому надо добавить событие, я собирался использовать сначала getElementsByTagName, затем RegExp
3) почему-то не был уверен, что onchange сработает, собирался поэкспериментировать с разными событиями
4) затем - постбэк

Но если основную часть можно написать в .NET, а не в JavaScript, мне этот вариант нравится гораздо больше.

Я попробую и отпишу. Спасибо за пример кода!
Старый 24.06.2014, 13:44   #4  
Dreadlock is offline
Dreadlock
Участник
Аватар для Dreadlock
 
298 / 224 (8) ++++++
Регистрация: 07.05.2009
Адрес: Москва
С методом getElementsByTagName есть один интересный момент, если у вас поле привязки данных, а скорее всего так оно и есть, то имя контрола будет ctl100...многоВсегоНеЧитабелного..._102 (как пример).
Зашивать такое имя в JavaScript не совсем корректно. Конечно можно попробовать в PageLoad генерить JavaScript и передавать в него этот ID или имя. Или поле привязки сделать шаблонным и присвоить ему нужный ID. Тогда можно и с getElementsByTagName работать не боясь, что что-то сломается (мысли в слух).

Удачи
Старый 24.06.2014, 13:56   #5  
Hyper is offline
Hyper
Участник
Соотечественники
 
163 / 29 (1) +++
Регистрация: 09.10.2003
Да, там имя типа ctl00$ctl00$m$g_fb191d40_6b28_4a75_9c9c_b1facd8fc1a3$ctl01$frmNameOfForm$grpNameOfGroup$ctl07

Но, как я понимаю, имя меняться не будет, так что если правильно идентифицировать элемент вначале, проблем быть не должно. Я с JavaScript не на ты, может и не учитываю что-то.

У поля ввода даты AxCtrlType="AxDTD", а у поля ввода времени AxCtrlType="AxDTT", я также собирался использовать эту интформацию для нахождения нужного элемента.

Если получится все сделать из .NET, во всем этом уже не будет необходимости.
Старый 24.06.2014, 14:27   #6  
Dreadlock is offline
Dreadlock
Участник
Аватар для Dreadlock
 
298 / 224 (8) ++++++
Регистрация: 07.05.2009
Адрес: Москва
Цитата:
Сообщение от Hyper Посмотреть сообщение
имя меняться не будет
Пока кто-нибудь перед элементом ...$ctl07 не влепит еще одно поле. Если это произойдет, то всё сломается.
Старый 24.06.2014, 20:16   #7  
Hyper is offline
Hyper
Участник
Соотечественники
 
163 / 29 (1) +++
Регистрация: 09.10.2003
Цитата:
Сообщение от Dreadlock Посмотреть сообщение
Я рекурсивно обходил все элементы на форме и добавлял скрипт
А откуда берется ControlCollection?

Или я чего-то не понимаю, или для аксаптовской формы этот метод все-таки не подходит. Мы имеем дело с объектами типа AxBoundField, а не Control или WebControl, и там нет свойства Attributes или, к примеру, ClientID и т.п.

В итоге мне пока не ясно, как можно повесить событие onchange на произвольный аксаптовский веб-контрол.
Старый 24.06.2014, 20:24   #8  
Dreadlock is offline
Dreadlock
Участник
Аватар для Dreadlock
 
298 / 224 (8) ++++++
Регистрация: 07.05.2009
Адрес: Москва
ControlCollection - коллекция контролов на странице, Page.Controls если не ошибаюсь.

Метод этот я скопировал, как я уже писал, и вставил в тему
Старый 25.06.2014, 17:56   #9  
Hyper is offline
Hyper
Участник
Соотечественники
 
163 / 29 (1) +++
Регистрация: 09.10.2003
Решил задачу с помощью JavaScript. С .NET не сложилось.

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

Мне постбэк был необходим на одном поле типа AxBoundField, условно назовем его TerminationDate.

Вначале я добавил следующие элементы на страницу:
PHP код:
<asp:HiddenField ID="PrevTerminationDate" runat="server" />
<
input type="hidden" id="PrevTerminationDateElementId" value="<%=PrevTerminationDate.ClientID%>" />
<
input type="hidden" id="TerminationDateElementId" /> 
Первый - для отслеживания, поменялось ли значение TerminationDate. Второй и третий - для хранения идентификаторов элементов PrevTerminationDate и TerminationDate.

После этого в начале страницы я добавил блок JavaScript:
PHP код:
<script type="text/javascript" language="javascript">
    
// <!CDATA[
    
Sys.Application.add_load(load);
    function 
load() {
        
addOnChangeEvents();
    }
    function 
addOnChangeEvents() {
        var 
regex = new RegExp("^.*AxFormName.AxGroupName.*$");
        var 
els document.getElementsByTagName("INPUT");
        for (var 
0els.lengthi++) {
            if (
els[i].getAttribute('AxCtrlType') == 'AxDTD' && regex.test(els[i].id)) {
                
els[i].onchange onTermDateChange;
                
els[i].onfocus onTermDateFocus;
                
document.getElementById('TerminationDateElementId').value els[i].id;
                break; 
//interested only in TerminationDate - first element in group
            
}
        }
    }
    function 
onTermDateChange() {
        var 
prevTermDateElId document.getElementById('PrevTerminationDateElementId').value;
        var 
termDateElId document.getElementById('TerminationDateElementId').value;
        
document.getElementById(prevTermDateElId).value document.getElementById(termDateElId).value;
    }
    function 
onTermDateFocus() {
        var 
prevTermDateElId document.getElementById('PrevTerminationDateElementId').value;
        var 
termDateElId document.getElementById('TerminationDateElementId').value;
        var 
termDateEl document.getElementById(termDateElId);
        if (
termDateEl.value != document.getElementById(prevTermDateElId).value) {
            if (
"createEvent" in document) {
                var 
evt document.createEvent("HTMLEvents");
                
evt.initEvent("change"falsetrue);
                
termDateEl.dispatchEvent(evt);
            }
            else 
termDateEl.fireEvent("onchange");
        }
    }
    
// ]]>
</script> 
Функция addOnChangeEvents запускается сразу после загрузки страницы. В ней мы находим требуемый элемент (аттрибут AxCtrlType для даты в utcDateTime всегда установлен в AxDTD). Наш элемент первый в группе, найти его не составляет труда.

Перехватываем события onchange и onfocus - используем функции onTermDateChange и onTermDateFocus.

В функции onTermDateChange (вызывается всегда, когда значение даты изменяется вручную) мы записываем введенное значение даты в элемент PrevTerminationDate. AutoPostBack="true" при этом также срабатывает без проблем.

В функции onTermDateFocus (вызывается, когда наш элемент получает фокус) мы проверяем, изменилось ли значение даты. Для сравнения используем значение, сохраненное в PrevTerminationDate. При выборе даты в окошке календаря проверка срабатывает сразу, т.к. фокус автоматически переходит на наш элемент. Итак, если дата поменялась, мы программно вызываем событие onchange. При этом:
а) вызывается onTermDateChange, новое значение даты сохраняется в PrevTerminationDate.
б) срабатывает postback (очевидно, AutoPostBack="true" также привязан к onchange).

Работает.
За это сообщение автора поблагодарили: Dreadlock (3).
Старый 25.06.2014, 18:45   #10  
Dreadlock is offline
Dreadlock
Участник
Аватар для Dreadlock
 
298 / 224 (8) ++++++
Регистрация: 07.05.2009
Адрес: Москва
Цитата:
Сообщение от Hyper Посмотреть сообщение
Проблема, как я сейчас понимаю, заключалась в том, что событие onchange не вызывается, если содержимое объекта изменяется программно.
Я уже писал, что onchange не работает, но точно помню делал просто и работало. Сегодня нашел название того самого события.
Вот здесь в самом низу написано про onpropertychange для IE.

У меня работало.

Спасибо за детальный ответ, думаю пригодится

З.Ы. Судя по приведенным JavaScrip'ам, как-то
Цитата:
"Я с JavaScript не на ты..."
Странно

Последний раз редактировалось Dreadlock; 25.06.2014 в 18:50.
Старый 25.06.2014, 19:04   #11  
Hyper is offline
Hyper
Участник
Соотечественники
 
163 / 29 (1) +++
Регистрация: 09.10.2003
Пробовал и onpropertychange, и многое другое.

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

Опять-таки, может, я чего-то не учитываю, но в моих тестах onpropertychange ничем не помогло.

Насчет JavaScript - кусок вышеприведенного кода у меня занял часы. Был бы я с JavaScript на ты, не было бы этих мучений.
Теги
ax2012, enterprise portal, utcdatetime

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
emeadaxsupport: AxUpdatePortal.exe does not update Enterprise Portal when not running from an elevated command prompt Blog bot DAX Blogs 0 26.07.2009 15:07
Solutions Monkey: Microsoft Dynamics AX 2009 Enterprise Portal / Role Centers - Deployment Tips-n-Tricks – 3 Blog bot DAX Blogs 0 27.10.2008 08:05
Solutions Monkey: Enterprise Portal Screencasts at Channel9.msdn.com Blog bot DAX Blogs 6 01.07.2008 19:38
jinx: Microsoft Dynamics AX 2009 Enterprise Portal Entwicklung Samples Blog bot DAX auf Deutsch 0 27.06.2008 04:06
JOPX: Integrating MOSS 2007 and Dynamics AX Part II - installing and configuring Dynamics AX Enterprise Portal Blog bot DAX Blogs 0 02.03.2008 06:42

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 14:24.