Изменить значение поля в карточке редактирования раздела при добавлении записи на деталь.
Здравствуйте!
Такой вопрос:
Есть карточка редактирования раздела "Заявление на перс. дни", у неё есть деталь "Персональный день в заявлении", при добавлении или изменении значения в которой - требуется изменить значение числового поля Кол-во(дней) указать количество выбранных дней добавленных на деталь. (в атаче наглядно)
При изменении\добавлении с детали "Персональных дней" мы меняем на уровне обьекта Entity значение У заявления (тоесть у записи открытой карточки), и само собой разумеется - нужно установить соответствующее на текущей открытой карточке Заявления.
Для этого в карточке редактирования "Заявления на перс. день" после PageOnLoadCompleete я сохраняю в сессии Uid процесса так
if (session["FreeDayStatementPageProcessUid"] == null) {
session.Add("FreeDayStatementPageProcessUid", Page.Process.InstanceUId);
}
В карточке редактирования детали "Персональные дни" на нажатие кнопки Ok я вытаскиваю из сессии id процесса и высылаю ему сообщение, и сообщение то приходит. Код:
string freeDayStatementPageProcessUId = (string) session["FreeDayStatementPageProcessUid"];
if (!string.IsNullOrEmpty(freeDayStatementPageProcessUId ))
{
var process = UserConnection.ProcessEngine.FindProcessByUId(freeDayStatementPageProcessUId );
if (process != null)
{
process.ThrowEvent(process.InternalContext, "FreeDayInFreeDayStatementMessage");
}
}
return true;
И вот тут начинается самое интересное:
В процессе родительского окна (то есть Заявления) я пытаюсь установить значение полю. А поля нет т.к Page = null (в атаче картинка). При этом context и this это тот нужный процесс. Пробовал сохранять Page в параметр отдельно, и тоже Null. Также пытался передавать в ThrowEvent ранее сохраненный контекст Заявления - всё безрезультатно. До контролов не добраться.
Подскажите что я делаю не так?
Сразу скажу что реализация не конечная это своего рода проверка метода.
Нравится
Похожее делали с помощью клиентской логики.
На PageLoadComplete детали (у нас DiscountGridPage):
AddPageRefreshFunctionality(Page);
функция:
public static void AddPageRefreshFunctionality(DiscountGridPageSchemaUserControl Page) { const string methodName = "setNewColumnValues"; var script = ""; script += @"window."+methodName+ @" = function (newValues){ var ds = " + Page.OpportunityDataSource.ClientID + @"; ds.suspendAjaxEvents(); for(var columnName in newValues){ var column = ds.getColumnByName(columnName); if (column) { ds.setColumnValue(columnName, newValues[columnName]); } } ds.resumeAjaxEvents(); }; window.ReloadOpportunityInfo = function () { var layout = " + Page.CustomerDiscountControlLayout.ClientID + @"; layout.callPageMethod('ThrowEvent',{signalName:'RefreshData'}); };"; script = ";(function(){" + script + "})();"; Page.AddScript(script); }
На детали на событии RefreshData вызываем функцию с параметрами Page и SelectedNodePrimaryColumnValue.
Она создаёт Entity основного раздела с новыми значениями полей:
public static void OnDiscountFieldsChanged(DiscountGridPageSchemaUserControl Page, Guid opportunityId) { var row = FetchCurrentOpportunity(Page.UserConnection, opportunityId, true); var isChangesOnCardFlag = false; if (row.CDStockDiscountUse != (bool) Page.CDStockDiscountUseCheckBox.Value) { row.CDStockDiscountUse = (bool)Page.CDStockDiscountUseCheckBox.Value; isChangesOnCardFlag = true; } if (row.CDConsideredKS != (bool)Page.CDConsideredKSCheckBox.Value) { row.CDConsideredKS = (bool)Page.CDConsideredKSCheckBox.Value; isChangesOnCardFlag = true; } if (row.CDConsideredSK != (bool)Page.CDConsideredSKCheckBox.Value) { row.CDConsideredSK = (bool)Page.CDConsideredSKCheckBox.Value; isChangesOnCardFlag = true; } if (isChangesOnCardFlag) { OpportunityLogicHelper.UpdateFinalDiscount(row); } UpdateOpportunityFields(Page, row); }
Тут в предпоследней строке вызывается функция, которая делает Update в базе для полей в записи в разделе (не показана). Именно Update — чтобы не сработали события на объекте.
А в последней — обновление в карточке, о котором Вы спрашивали:
private static void UpdateOpportunityFields(DiscountGridPageSchemaUserControl Page, Opportunity opportunity) { if (opportunity != null) { var info = AmountColumnns.ToDictionary(s => s, opportunity.GetColumnValue); var script = "if (window.setNewColumnValues) { window.setNewColumnValues(" + JsonConvert.SerializeObject(info) + "); }"; script = ";(function(){" + script + "})();"; Page.AddScript(script); } }
Там ещё много другой логики, что-то мог и пропустить.
Решение в лоб повесил на события детали DataSourceRemoved, DataSourceLoadRowsResponseRegistered:
var durationEditControl= ControlUtilities.FindControl(Page.AspPage.Controls[0], "DurationEdit", true) as Terrasoft.UI.WebControls.Controls.FloatEdit; if (durationEditControl != null && SelectedNodePrimaryColumnValue != null) { var freeDayStatementEntity = new Terrasoft.Configuration.FreeDayStatement(UserConnection); Guid freeDayStatementId = Guid.Empty; freeDayStatementId = new Guid(SelectedNodePrimaryColumnValue.ToString()); if (freeDayStatementEntity.FetchFromDB(freeDayStatementId)) { durationEditControl.SetValue(freeDayStatementEntity.GetTypedColumnValue<decimal>("Duration")); } } return true;
В объекте Заяление на перс дни, при добавлении на деталь персональных дней отрабатывает логика в entity которая меняет значение той записи для которой добавили дни.
Можно и так. Возможно, стоит одновременно менять значение поля и в БД (с использованием Entity или Update), чтобы не возникло расхождение, если пользователь поменяет на детали и нажмёт в карточке отмену. Лучше даже Update, чтобы возможный БП по таблице раздела сработал только раз, при нажатии ОК.
"Зверев Александр" написал:Можно и так. Возможно, стоит одновременно менять значение поля и в БД (с использованием Entity или Update), чтобы не возникло рахождение, если пользователь поменяет на детали и нажмёт в карточке отмену. Лучше даже Update, чтобы возможный БП по таблице раздела сработал только раз, при нажатии ОК.
Да именно так и делаю через entity на вставку или удалении в детали срабатывает изменение записи.