在 Acumatica 中动态改变 PXSelector

Dynamically changing PXSelector in Acumatica

我有以下用例:

Acumatica 组合框/下拉列表,可以有 8 个左右的值,selection 决定了 table/DAC 用于在 PXSelector 中呈现。

例如:

-如果用户 select 选项 a,我需要在 PXSelector 中显示来自 Table A

的值

-如果用户 select 选项 b,我需要在 PXSelector 中显示来自 Table B

的值

-如果用户 select 选项 c,我需要在 PXSelector 中显示来自 Table C

的值

我知道我必须使用自定义选择器属性,但具体操作方法尚不清楚。

如您所说,您需要实现一个继承自 PXCustomSelectorAttribute class 的属性。

1- 创建一个 class PromptType,其中包含一个 IDDescription,其中包含每个 table 的类型。

public class PromptType
{
    public Type Id { get; set;}
    public Type Description { get; set; }
}

2- 实现 customSelectorAttribute,如下所示:

public class MyCustomSelector : PXCustomSelectorAttribute
{
    //Class used to display the data into the selector
    [Serializable]
    public class TableDummy : IBqlTable
    {
        #region Id

        [PXInt(IsKey = true)]
        [PXUIField(DisplayName = "Id")]
        public int? Id { get; set; }

        public class id : IBqlField { }

        #endregion


        #region Description

        [PXString(60, IsUnicode = true, InputMask = "")]
        [PXUIField(DisplayName = "Description", Visibility = PXUIVisibility.SelectorVisible)]
        public string Description { get; set; }

        public class description : IBqlField { }

        #endregion
    }

    //Selected table
    private Type _TableSelection;

    //Tables Ids. You can add as much field ID as you want
    private Type _TableFieldA;
    private Type _TableFieldB;
    private Type _TableFieldC;

    //Tables description fields
    private Type _TableAFieldDesc;
    private Type _TableBFieldDesc;
    private Type _TableCFieldDesc;


    public MyCustomSelector(Type tableSelection, Type tableFieldA, Type tableAFieldDesc, Type tableFieldB, Type tableBFieldDesc, Type tableFieldC, Type tableCFieldDesc) : base(typeof(TableDummy.id))
    {
        _TableSelection = tableSelection;
        _TableFieldA = tableFieldA;
        _TableFieldB = tableFieldB;
        _TableFieldC = tableFieldC;
        _TableAFieldDesc = tableAFieldDesc;
        _TableBFieldDesc = tableBFieldDesc;
        _TableCFieldDesc = tableCFieldDesc;
    }

    //Get the name of the selected table by using the private field _TableSelection.
    private string GetSelection()
    {
        var cache = _Graph.Caches[_BqlTable];
        return cache.GetValue(cache.Current, _TableSelection.Name)?.ToString();
    }

    //Return a pompt instance based on the selected table in the dropdown.
    private PromptType GetSelectedTableField(string selectedTable)
    {
        switch (selectedTable)
        {
            case "A":
                return new PromptType() { Id = _TableFieldA, Description = _TableAFieldDesc };
            case "B":
                return new PromptType() { Id = _TableFieldB, Description = _TableBFieldDesc };
            case "C":
                return new PromptType() { Id = _TableFieldC, Description = _TableCFieldDesc };
            default:
                return new PromptType() { Id = _TableFieldA, Description = _TableAFieldDesc };
        }
    }

    //Return the records
    public IEnumerable GetRecords()
    {
        var selectedField = GetSelectedTableField(GetSelection());
        var selectedTable = BqlCommand.GetItemType(selectedField.Id);

        var select = BqlCommand.Compose(
                        typeof(Select<>),
                            selectedTable
                        );

        var cmd = BqlCommand.CreateInstance(select);
        PXView view = new PXView(_Graph, true, cmd);

        foreach (var row in view.SelectMulti())
        {
            var id = (int?)view.Cache.GetValue(row, selectedField.Id.Name);
            var description = view.Cache.GetValue(row, selectedField.Description.Name)?.ToString();
            yield return new TableDummy { Id = id, Description = description };
        }
    }
}

您可以通过传递所需数量的 table 来更改自定义属性的构造函数。


3- 实现自定义属性后,您可以像这样在您的领域中使用它:

#region DropDown to select a table
[PXDBString(1)]
[PXUIField(DisplayName = "Table Selection")]
[PXStringList(
    new string[]
    {
        "A",
        "B",
        "C"
    },
    new string[]
    {
            "Table A",
            "Table B",
            "Table C"
    })]
public virtual string UsrTableSelection { get; set; }
public abstract class usrTableSelection : IBqlField
{
}
#endregion

#region Selector
[PXDBInt]
[PXUIField(DisplayName = "Table Selector")]
[MyCustomSelector(
    typeof(APRegisterExt.usrTableSelection), 
    typeof(TableA.id),typeof(TableA.description),
    typeof(TableB.id), typeof(TableB.description),
    typeof(PX.Objects.AR.Customer.bAccountID), 
    typeof(PX.Objects.AR.Customer.acctName))]
public virtual int? UsrTableSelector { get; set; }

public abstract class usrTableSelector : IBqlField
{
}
#endregion

4- 此外,您不应忘记设置 tables 字段的可见性。我指的是您要在选择器中显示的 tables (DACs)。假设您想根据下拉列表显示 TableATableBTableC,您需要设置要在选择器中使用的字段的可见性。

这是我在测试期间使用的 table 之一的实现:

[Serializable]
public class TableA : IBqlTable
{
    #region Id

    [PXDBInt(IsKey = true)]
    [PXUIField(DisplayName = "Id")]
    public int? Id { get; set; }

    public class id : IBqlField { }

    #endregion


    #region Description

    [PXDBString(60, IsUnicode = true, InputMask = "")]
    [PXUIField(DisplayName = "Description", Visibility = PXUIVisibility.SelectorVisible)]
    public string Description { get; set; }

    public class description : IBqlField { }

    #endregion


    #region InfoA

    [PXDBString(60, IsUnicode = true, InputMask = "")]
    [PXUIField(DisplayName = "Info A", Visibility = PXUIVisibility.SelectorVisible)]
    public string InfoA { get; set; }

    public class infoA : IBqlField { }

    #endregion
}

通过将可见性设置为 SelectorVisible,该字段将自动显示在 PXSelector 中。


5- 最后,您需要在下拉菜单中将 CommitChanges 设置为 True,并在表单字段中将 AutoRefresh 设置为 True。这是一个例子:

<px:PXDropDown runat="server" ID="CstPXDropDown1" DataField="UsrTableSelection" CommitChanges="True" />
<px:PXSelector runat="server" ID="CstPXSelector2" DataField="UsrTableSelector" AutoRefresh="True" />