Dynamically changing PXSelector in Acumatica

后端 未结 1 1336
温柔的废话
温柔的废话 2021-01-14 01:54

I have the following use case:

Acumatica combo box / dropdown, which can have 8 or so values, the selection of which determines the table / DAC used to present in a

1条回答
  •  北恋
    北恋 (楼主)
    2021-01-14 02:17

    As you said, you need to implement an attribute that inherits from the PXCustomSelectorAttribute class.

    1- Create a class PromptType that will have an ID and Description that will hold the types of each table.

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

    2- Implement the customSelectorAttribute, like this:

    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 };
            }
        }
    }
    

    You can change the constructor of the custom attribute, by passing the desired number of tables.


    3- Once you have implemented your custom attribute, you can use it in your field like this:

    #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- Also, you should not forget to set the visibility on your tables fields. I'm referring to the tables (DACs) that you want to display in the selector. Let say that you want to display TableA, TableB or TableC depending on your drop down, you need to set the visibility on the fields that you are going to use in the selector.

    Here's the implementation of one of the tables that I used during my tests:

    [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
    }
    

    By setting the visibility to SelectorVisible, the field will be displayed automatically in the PXSelector.


    5- Finally, you need to set CommitChanges to True on your dropdown and set AutoRefresh to True on your form field. Here's an example:

    
    
    

    0 讨论(0)
提交回复
热议问题