Global Generi c Событие обновления поля - PullRequest
0 голосов
/ 25 марта 2020

У меня есть более 50 пользовательских парных полей «Дюймы» и «Сантиметры», каждое из которых включено и доступно для редактирования. Мне нужно обновить «Дюймы», если пользователь изменил значение «Сантиметров» и стиха на визу. Я смог сделать это, используя SetValuePending на одном из парных полей и SetValueExt на другом во время события «Обновление поля». Мой вопрос, есть ли способ сделать это на более высоком уровне без необходимости делать событие Field_Updated для всех 100+ полей. Я знаю, что формулы будут создавать круговую ссылку, поэтому не могут быть использованы. Спасибо

Ответы [ 3 ]

0 голосов
/ 25 марта 2020

Вы можете сделать это с помощью выражения PXFormula + ExternalValue BQL (например, PXRowUpdatedEventArgs.ExternalCall), что предотвратит циклическую ссылку между парами полей. Идея состоит в том, чтобы вычислять поле, только когда связанное поле было изменено пользователем из пользовательского интерфейса (ExternalCall = true), и пропускать вычисления, когда связанное поле обновляется по формуле (ExternalCall = false).

public class centimetersInInches : PX.Data.BQL.BqlDecimal.Constant<centimetersInInches>
{
    public centimetersInInches() : base(2.54m) { }
}

[PXDecimal]
[PXUIField(DisplayName = "Inches")]
[PXUnboundDefault(TypeCode.Decimal, "0.0")]
[PXFormula(typeof(ExternalValue<Div<centimeters, centimetersInInches>>))]
public virtual decimal? Inches { get; set; }
public abstract class inches : PX.Data.BQL.BqlDecimal.Field<inches> { }

[PXDecimal]
[PXUIField(DisplayName = "Centimeters")]
[PXUnboundDefault(TypeCode.Decimal, "0.0")]
[PXFormula(typeof(ExternalValue<Mult<inches, centimetersInInches>>))]
public virtual decimal? Centimeters { get; set; }
public abstract class centimeters : PX.Data.BQL.BqlDecimal.Field<centimeters> { }

А aspx

<px:PXGridColumn DataField="Inches" CommitChanges="True" />
<px:PXGridColumn DataField="Centimeters" CommitChanges="True" />
0 голосов
/ 26 марта 2020

Ну, вы можете использовать один метод для обработки FieldUpdated событий для всех полей, которые вам нужны, используя метод graph FieldUpdated.AddHandler в конструкторе. Чтобы получить имя поля, просто расширьте стандартный делегат Acumatica FieldUpdated одним дополнительным параметром (например, name) и вставьте его во время вызова FieldUpdated.AddHandler. Вот пример с экраном «Счета-фактуры и заметки» и графиком ARInvoiceEntry.

public ARInvoiceEntry()
{
    FieldUpdated.AddHandler(typeof(ARTran), typeof(ARTran.inches).Name, (sender, e) => CommonFieldUpdated(sender, e, typeof(ARTran.inches).Name));
    FieldUpdated.AddHandler(typeof(ARTran), typeof(ARTran.centimeters).Name, (sender, e) => CommonFieldUpdated(sender, e, typeof(ARTran.centimeters).Name));
    ...
}

protected virtual void CommonFieldUpdated(PXCache sender, PXFieldUpdatedEventArgs e, string name)
{
    // do something
}

Кроме того, вы можете динамически добавлять обработчики, используя коллекцию полей, например

foreach(var field in Caches[typeof(ARTran)].Fields)
{
    // add handler depends on field name
}
0 голосов
/ 25 марта 2020

Вы можете использовать событие RowUpdated и сравнить старую строку с новой строкой, чтобы определить, какое поле изменилось. Я согласен с тем, что предпочтительнее хранить все логи c в одном методе.

public virtual void DAC_RowUpdated(PXCache sender, PXRowUpdatedEventArgs e)
{
    DAC row = e.Row as DAC;
    DAC oldRow = e.OldRow as DAC;
    if (row == null || oldRow == null) return;

    // Compare old row with new row to determine which field changed
    if (row.Inches != oldRow.Inches)
    {
        // Inches field changed, update CM value
        row.CM = row.Inches * INCHES_TO_CM_CONSTANT;
    }

    // Add more conditions for the other fields
    [..]
}

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

Да, я бы тоже не советовал, вы могли бы использовать свойство Setter DA C.

public string _Inches
public virtual string Inches
{
   get 
   { 
       return this._Inches; 
   }
   set 
   { 
       this._Inches = value;
       this.CM = value * INCHES_TO_CM_CONSTANT; 
   }
}

Для всех решений (кроме атрибутов Formula / DA C) я думаю, что условие нужно остановить рекурсия должна быть возможной, если это абсолютно необходимо:

if (this.CM != value * INCHES_TO_CM_CONSTANT)
    this.CM = value * INCHES_TO_CM_CONSTANT;

Идеально правильное использование / обход SetValueExt для контроля, когда возникают события (метод Ext вызывает события), было бы достаточно, чтобы остановить бесконечные циклы.

...