如何将属性(从CSAnswer)作为选择列添加到客户和供应商数据输入屏幕上的客户ID和供应商ID查找?
我尝试从StackOverflow文章Add Attributes fields on Inventory Lookup实施步骤,但它对我不起作用。
答案 0 :(得分:2)
与 InventoryItem InventoryCD 字段InventoryRawAttribute
和CustomerRawAttribute
上使用的VendorRawAttribute
不同,装饰 AcctCD 客户和供应商 DAC中的strong>字段分别在其构造函数中明确定义选择器网格列。如API Reference中所述,如果没有为选择器网格指定列,则将 PXUIField 属性的可见性属性设置为{{{ 1}}将自动添加到选择器网格中。
PXUIVisibility.SelectorVisible
要将属性字段添加到客户ID选择器,我们将首先实现自定义 AttributesFieldWithColumnsAttribute :
[PXDBString(InputMask = "", IsUnicode = true)]
[PXUIField(DisplayName = "Inventory ID", Visibility = PXUIVisibility.SelectorVisible)]
public sealed class InventoryRawAttribute : AcctSubAttribute
{
...
public InventoryRawAttribute()
: base()
{
...
PXDimensionSelectorAttribute attr = new PXDimensionSelectorAttribute(
DimensionName, SearchType, typeof(InventoryItem.inventoryCD));
...
}
...
}
[PXDBString(30, IsUnicode = true, InputMask = "")]
[PXUIField(DisplayName = "Customer ID", Visibility = PXUIVisibility.Visible)]
public sealed class CustomerRawAttribute : AcctSubAttribute
{
...
public CustomerRawAttribute()
: base()
{
...
_Attributes.Add(new PXDimensionSelectorAttribute(
DimensionName, SearchType, typeof(Customer.acctCD),
typeof(Customer.acctCD),
typeof(Customer.acctName),
typeof(Customer.customerClassID),
typeof(Customer.status),
typeof(Contact.phone1),
typeof(Address.city),
typeof(Address.countryID),
typeof(Contact.eMail)));
...
}
}
[PXDBString(30, IsUnicode = true, InputMask = "")]
[PXUIField(DisplayName = "Vendor", Visibility = PXUIVisibility.Visible)]
public sealed class VendorRawAttribute : AcctSubAttribute
{
...
public VendorRawAttribute(Type where)
{
...
PXDimensionSelectorAttribute attr;
_Attributes.Add(attr = new PXDimensionSelectorAttribute(
DimensionName, SearchType, typeof(Vendor.acctCD),
typeof(Vendor.acctCD),
typeof(Vendor.acctName),
typeof(Vendor.vendorClassID),
typeof(Vendor.status),
typeof(Contact.phone1),
typeof(Address.city),
typeof(Address.countryID));
...
}
}
我们的下一步是创建自定义 CustomerRawWithAttributes 属性,重复密封的 CustomerRaw 属性的功能,并使用<中定义的属性扩展选择器列的列表strong> AttributesFieldWithColumns 属性:
public class AttributesFieldWithColumnsAttribute : CRAttributesFieldAttribute
{
private string[] attributeNames;
public AttributesFieldWithColumnsAttribute(string[] attributeNames, Type classIDField, Type noteIdField, Type[] relatedEntityTypes)
: base(classIDField, noteIdField)
{
this.attributeNames = attributeNames;
}
public string[] GetAttributeColumns()
{
return attributeNames;
}
public override void CacheAttached(PXCache sender)
{
_IsActive = true;
base.CacheAttached(sender);
}
public override void CommandPreparing(PXCache sender, PXCommandPreparingEventArgs e)
{
base.CommandPreparing(sender, e);
if (e.BqlTable == null && aggregateAttributes && sender.GetItemType().IsDefined(typeof(PXProjectionAttribute), true))
{
e.BqlTable = _BqlTable;
}
}
protected override void AttributeFieldSelecting(PXCache sender, PXFieldSelectingEventArgs e, PXFieldState state, string attributeName, int idx)
{
if (attributeNames.Any(attributeName.Equals))
{
state.Visible = true;
state.Visibility = PXUIVisibility.Visible;
//Out-of-the-box DisplayName is prefixed with "$Attributes$-" - if you need to take that off.
state.DisplayName = (!String.IsNullOrEmpty(state.DisplayName)) ? (state.DisplayName.Replace("$Attributes$-", "")) : attributeName;
}
base.AttributeFieldSelecting(sender, e, state, attributeName, idx);
}
protected override void AttributeCommandPreparing(PXCache sender, PXCommandPreparingEventArgs e, PXFieldState state, string attributeName, int iField)
{
if (e.Operation == PXDBOperation.External && e.Table != null &&
e.Table.IsDefined(typeof(PXSubstituteAttribute), false))
{
e = new PXCommandPreparingEventArgs(e.Row, e.Value, e.Operation, e.Table.BaseType, e.SqlDialect);
}
base.AttributeCommandPreparing(sender, e, state, attributeName, iField);
}
}
我们的最后一步是在 CustomerMaint BLC扩展程序中定义2个 CacheAttached 处理程序,以修改客户的属性< strong> AcctCD 和属性字段:
[PXDBString(30, IsUnicode = true, InputMask = "")]
[PXUIField(DisplayName = "Customer ID", Visibility = PXUIVisibility.Visible)]
public sealed class CustomerRawWithAttributesAttribute : AcctSubAttribute
{
public const string DimensionName = "CUSTOMER";
public CustomerRawWithAttributesAttribute()
: base()
{
Type SearchType = typeof(Search2<Customer.acctCD,
LeftJoin<Contact, On<Contact.bAccountID, Equal<Customer.bAccountID>, And<Contact.contactID, Equal<Customer.defContactID>>>,
LeftJoin<Address, On<Address.bAccountID, Equal<Customer.bAccountID>, And<Address.addressID, Equal<Customer.defAddressID>>>>>,
Where<Match<Current<AccessInfo.userName>>>>);
_fields = new Type[] { typeof(Customer.acctCD), typeof(Customer.acctName),
typeof(Customer.customerClassID), typeof(Customer.status), typeof(Contact.phone1),
typeof(Address.city), typeof(Address.countryID), typeof(Contact.eMail) };
_Attributes.Add(new PXDimensionSelectorAttribute(DimensionName, SearchType, typeof(Customer.acctCD), _fields));
_SelAttrIndex = _Attributes.Count - 1;
((PXDimensionSelectorAttribute)_Attributes[_SelAttrIndex]).CacheGlobal = true;
Filterable = true;
}
public override void CacheAttached(PXCache sender)
{
base.CacheAttached(sender);
string name = _FieldName.ToLower();
sender.Graph.FieldSelecting.RemoveHandler(sender.GetItemType(), name, GetAttribute<PXDimensionSelectorAttribute>().FieldSelecting);
sender.Graph.FieldSelecting.AddHandler(sender.GetItemType(), name, FieldSelecting);
}
private readonly Type[] _fields;
private string[] _FieldList = null;
private string[] _HeaderList = null;
private void PopulateFields(PXCache sender)
{
if (_FieldList == null)
{
var attributeFields = new Dictionary<string, string>();
foreach (var fAttr in sender.GetAttributesOfType<AttributesFieldWithColumnsAttribute>(null, null))
{
foreach (string attribute in fAttr.GetAttributeColumns())
{
attributeFields.Add(attribute, fAttr.FieldName);
}
}
_FieldList = new string[_fields.Length + attributeFields.Count];
_HeaderList = new string[_fields.Length + attributeFields.Count];
for (int i = 0; i < _fields.Length; i++)
{
Type cacheType = BqlCommand.GetItemType(_fields[i]);
PXCache cache = sender.Graph.Caches[cacheType];
if (cacheType.IsAssignableFrom(typeof(BAccountR)) ||
_fields[i].Name == typeof(BAccountR.acctCD).Name ||
_fields[i].Name == typeof(BAccountR.acctName).Name)
{
_FieldList[i] = _fields[i].Name;
}
else
{
_FieldList[i] = cacheType.Name + "__" + _fields[i].Name;
}
_HeaderList[i] = PXUIFieldAttribute.GetDisplayName(cache, _fields[i].Name);
}
int index = _fields.Length;
foreach (var attributeField in attributeFields)
{
string fieldName = attributeField.Key + "_" + attributeField.Value;
var fs = sender.GetStateExt(null, fieldName) as PXFieldState;
if (fs != null)
{
_FieldList[index] = fieldName;
_HeaderList[index] = fs.DisplayName;
}
index++;
}
}
var attr = GetAttribute<PXDimensionSelectorAttribute>().GetAttribute<PXSelectorAttribute>();
attr.SetColumns(_FieldList, _HeaderList);
}
public void FieldSelecting(PXCache sender, PXFieldSelectingEventArgs e)
{
if (AttributeLevel == PXAttributeLevel.Item || e.IsAltered)
{
PopulateFields(sender);
}
PXFieldSelecting handler = GetAttribute<PXDimensionSelectorAttribute>().FieldSelecting;
handler(sender, e);
}
}
应采取类似步骤将属性字段添加到供应商ID选择器。我们创建自定义 VendorRawWithAttributes 属性,重复密封的 VendorRaw 属性的功能,并使用 AttributesFieldWithColumns 中定义的属性扩展选择器列的列表属性:
public class CustomerExt : PXGraphExtension<CustomerMaint>
{
[PXMergeAttributes(Method = MergeMethod.Append)]
[PXRemoveBaseAttribute(typeof(CustomerRawAttribute))]
[CustomerRawWithAttributes(IsKey = true)]
public void Customer_AcctCD_CacheAttached(PXCache sender) { }
[AttributesFieldWithColumns(new[] { "COMPREV", "COMPSIZE" },
typeof(Customer.customerClassID),
typeof(BAccount.noteID),
new[]
{
typeof(BAccount.classID),
typeof(Vendor.vendorClassID)
})]
public void Customer_Attributes_CacheAttached(PXCache sender) { }
}
之后我们需要在 VendorMaint BLC扩展程序中定义2个 CacheAttached 处理程序,以修改供应商的属性< strong> AcctCD 和属性字段:
[PXDBString(30, IsUnicode = true, InputMask = "")]
[PXUIField(DisplayName = "Vendor", Visibility = PXUIVisibility.Visible)]
public sealed class VendorRawWithAttributesAttribute : AcctSubAttribute
{
public const string DimensionName = "VENDOR";
public VendorRawWithAttributesAttribute()
: base()
{
Type SearchType = typeof(Search2<Vendor.acctCD,
LeftJoin<Contact, On<Contact.bAccountID, Equal<Vendor.bAccountID>, And<Contact.contactID, Equal<Vendor.defContactID>>>,
LeftJoin<Address, On<Address.bAccountID, Equal<Vendor.bAccountID>, And<Address.addressID, Equal<Vendor.defAddressID>>>>>,
Where<Match<Current<AccessInfo.userName>>>>);
_fields = new Type[] { typeof(Vendor.acctCD), typeof(Vendor.acctName),
typeof(Vendor.vendorClassID), typeof(Vendor.status), typeof(Contact.phone1),
typeof(Address.city), typeof(Address.countryID) };
_Attributes.Add(new PXDimensionSelectorAttribute(DimensionName, SearchType, typeof(Customer.acctCD), _fields));
_SelAttrIndex = _Attributes.Count - 1;
((PXDimensionSelectorAttribute)_Attributes[_SelAttrIndex]).CacheGlobal = true;
Filterable = true;
}
public override void CacheAttached(PXCache sender)
{
base.CacheAttached(sender);
string name = _FieldName.ToLower();
sender.Graph.FieldSelecting.RemoveHandler(sender.GetItemType(), name, GetAttribute<PXDimensionSelectorAttribute>().FieldSelecting);
sender.Graph.FieldSelecting.AddHandler(sender.GetItemType(), name, FieldSelecting);
}
private readonly Type[] _fields;
private string[] _FieldList = null;
private string[] _HeaderList = null;
private void PopulateFields(PXCache sender)
{
if (_FieldList == null)
{
var attributeFields = new Dictionary<string, string>();
foreach (var fAttr in sender.GetAttributesOfType<AttributesFieldWithColumnsAttribute>(null, null))
{
foreach (string attribute in fAttr.GetAttributeColumns())
{
attributeFields.Add(attribute, fAttr.FieldName);
}
}
_FieldList = new string[_fields.Length + attributeFields.Count];
_HeaderList = new string[_fields.Length + attributeFields.Count];
for (int i = 0; i < this._fields.Length; i++)
{
Type cacheType = BqlCommand.GetItemType(_fields[i]);
PXCache cache = sender.Graph.Caches[cacheType];
if (cacheType.IsAssignableFrom(typeof(BAccountR)) ||
_fields[i].Name == typeof(BAccountR.acctCD).Name ||
_fields[i].Name == typeof(BAccountR.acctName).Name)
{
_FieldList[i] = _fields[i].Name;
}
else
{
_FieldList[i] = cacheType.Name + "__" + _fields[i].Name;
}
_HeaderList[i] = PXUIFieldAttribute.GetDisplayName(cache, _fields[i].Name);
}
int index = _fields.Length;
foreach (var attributeField in attributeFields)
{
string fieldName = attributeField.Key + "_" + attributeField.Value;
var fs = sender.GetStateExt(null, fieldName) as PXFieldState;
if (fs != null)
{
_FieldList[index] = fieldName;
_HeaderList[index] = fs.DisplayName;
}
index++;
}
}
var attr = GetAttribute<PXDimensionSelectorAttribute>().GetAttribute<PXSelectorAttribute>();
attr.SetColumns(_FieldList, _HeaderList);
}
public void FieldSelecting(PXCache sender, PXFieldSelectingEventArgs e)
{
if (AttributeLevel == PXAttributeLevel.Item || e.IsAltered)
{
PopulateFields(sender);
}
PXFieldSelecting handler = GetAttribute<PXDimensionSelectorAttribute>().FieldSelecting;
handler(sender, e);
}
}
请注意,AR303000.aspx或AP303000.aspx不需要进行其他更改,以允许用户按自定义选择器中的属性值进行搜索。