Взаимодействие с жизненным циклом страницы
Итак, запись в таблице отредактирована, осталось её сохранить. Первое, что приходит на ум - это целиком AJAX решение, когда данные собираются из редактируемой строки DataGrid, отправляются на сервер, и в случае успеха клиентская PostBack функция перерисовывает строку таблицы уже только для просмотра. Однако, если первая часть этой идеи не вызывает никаких трудностей, то перерисовка таблицы ставит несколько вопросов. Во-первых, для общего случая нужно найти способ получить с сервера представление ItemTemplate каждого элемента управления в редактируемой строке, т.е. как отображаются колонки в режиме просмотра. Далее полученным с сервера данным вместе с представлением найти соответствующие места на странице куда всё это вставить. И произвести вставку.
Как альтернативный вариант, можно попробовать собрать на сервере всю строку таблицы, найти на клиенте её место на странице и вставить. Даже если найти способ всё это сделать относительно небольшим количеством кода, остается следующий вопрос. Что делать с состоянием страницы, ведь ViewState страницы хранит другие данные и при первом же PostBack (например, в случае фильтрации или сортировки), таблица всё еще будет считать, что определенная строка находится в состоянии редактирования, а значения элементов "поднимутся" из ViewState старые. "Достучаться" до объектной модели не возможно, так как при асинхронном вызове, объектная модель страницы не инициализирована, а значит AJAX метод ничего не знает о существующих в жизненном цикле страницы объектах.
Теоретически, можно поступить как это делает ASP .NET 2, а именно инициализировать почти все шаги жизненного цикла, кроме Render. Далее изменить объекты страницы на новые и это гарантирует, что при следующем обращении к странице мы получим ожидаемый положительный результат. При таком решении есть два значительных минуса: для достаточно простого логического действия, отрисовки строки таблицы, приходится писать много кода, и при этом нагрузка на сервер остается на том же уровне, что и при простом PostBack. По сути, единственным плюсом становится то, что пользователь не видит как перерисовывается вся страница.
Пока что, на мой взгляд правильным решением будет вызов функции __doPostBack в клиентской CallBack функции.
Итак, при нажатии на клиенте кнопки Update, вызывается следующая функция:
function updateEq(controlID) {
var _eqInfo = AdminEditor.EqEditor.GetEqInfoMetaData().value;
var lastind = controlID.lastIndexOf('_');
var prefix = controlID.substring(0, lastind + 1);
_eqInfo.DepartmentID = document.getElementById(prefix + "ddlstDepartment").value;
_eqInfo.DeviceModelID = document.getElementById(prefix + "ddlstDevicemodelID").value;
_eqInfo.OfficeID = document.getElementById(prefix + "ddlstOffice").value;
_eqInfo.RoomID = document.getElementById(prefix + "ddlstRoom").value;
_eqInfo.InvNumber = document.getElementById(prefix + "txtInvNumber").value;
_eqInfo.Comment = document.getElementById(prefix + "txtComment").value;
tmp = document.getElementById(prefix + "txtComissDate").value;
if(tmp.length > 0) {
arr = tmp.split(".");
_eqInfo.ComissDate = new Date(arr[2], arr[1]-1, arr[0]);
}
_eqInfo.Discarded = document.getElementById(prefix + "chkDiscardedE").checked;
var deviceID = document.getElementById(prefix + "deviceID").value;
AdminEditor.EqEditor.UpdateEq(deviceID, _eqInfo, updateEq_callback);
}
В этом коде, нахождение элементов управления в строке по ID кнопки является более универсальным, чем в предыдущих примерах. Находится префикс, собираемый ASP.NET в зависимости от положения элемента управления в тех или иных панелях, пользовательских "контролах" и наконец, от номера редактируемой строки в таблице. Например, ниспадающий список выбора офиса в редактируемой строке может выглядеть так: grdEquipment__ctl6_ddlstOffice, что означает что он принадлежит таблице grdEquipment, строке _ctl6. Но, в общем префикс может быть и длиннее.
В первой строке вышеприведенной функции с сервера получаем структуру для дальнейшего заполнения её данными и отправки на сервер. Т.е. фактически, получаем метаданные, на основе которых формируем объект и отправляем его на сервер для сохранения. После вызова серверного метода, управление передается клиентской функции:
function updateEq_callback(res) {
if(res.value.length > 0) alert(res.value); else {
__doPostBack("","LoadData");
}
}
При отсутствии ошибок, она реализует PostBack страницы. Единственное, что примечательно в этом коде, это то что в качестве параметра eventArgument отправляю флаг "LoadData", который интерпретирую в жизненном цикле страницы как считывание актуальной информации из базы данных. В противном случае, таблица бы заполнилась данными из старого ViewState или из устаревшей сессии, что при обновлении неверно. Вот, пожалуй и всё.