I have some problems with the fact that when I select a value in the dropbox, or rather steel a checkmark, then it is automatically reset.
[Serializable]
public class KNRWCSAttributeExt : PXCacheExtension<CSAttribute>
{
public static bool IsActive() => true;
#region UsrSchemaField
[PXDBString(512, InputMask = "", IsUnicode = true)]
[PXUIField(DisplayName = "Multi Schema Field")]
//[PXUIVisible(typeof(Where<PX.CS.CSAttribute.controlType, Equal<CSAttribute.AttrType.giSelector>>))]
[PXStringList(new string[] {null}, new string[] {""}, ExclusiveValues = false)]
public virtual string UsrSchemaField { get; set; }
public abstract class usrSchemaField : PX.Data.BQL.BqlString.Field<usrSchemaField>
{
}
#endregion
}
I assume that this is due to the fact that the event is triggered again and the array is filled over and over again. With the usual examples that are already described on stackoverflow it works, but my code does not work
Tell me please how I can get data into DropDown once so that I can then select and the value is not reset.
public class KNRWCSAttributeMaintExt : PXGraphExtension<CSAttributeMaint>
{
public static bool IsActive() => true;
protected virtual void _(Events.RowSelected<CSAttribute> e)
{
if (e.Row == null)
{
return;
}
var el = e.Row as CSAttribute;
if (el.ControlType == CSAttribute.GISelector)
{
if (!string.IsNullOrEmpty(e.Row.ObjectName as string))
{
Type objType = System.Web.Compilation.PXBuildManager.GetType(e.Row.ObjectName, true);
PXCache objCache = Base.Caches[objType];
var fields = objCache.Fields
.Where(f => objCache.GetBqlField(f) != null ||
f.EndsWith("_Attributes", StringComparison.OrdinalIgnoreCase))
.Where(f => !objCache.GetAttributesReadonly(f).OfType<PXDBTimestampAttribute>().Any())
.Where(f => !string.IsNullOrEmpty((objCache.GetStateExt(null, f) as PXFieldState)?.ViewName))
.Where(f => f != "CreatedByID" && f != "LastModifiedByID")
.ToArray();
PXStringListAttribute.SetList<KNRWCSAttributeExt.usrSchemaField>(e.Cache, e.Row, fields, fields);
}
}
}
}
View
<asp:Content ID="cont2" ContentPlaceHolderID="phF" runat="Server">
<px:PXFormView ID="form" runat="server" DataSourceID="ds" Style="z-index: 100" Width="100%" DataMember="Attributes" Caption="Attribute Summary">
<Template>
<px:PXLayoutRule runat="server" StartColumn="True" ControlSize="M" LabelsWidth="SM" />
<px:PXSelector ID="edAttributeID" runat="server" DataField="AttributeID" AutoRefresh="True" DataSourceID="ds">
<GridProperties FastFilterFields="description" />
</px:PXSelector>
<px:PXTextEdit ID="edDescription" runat="server" AllowNull="False" DataField="Description" />
<px:PXDropDown CommitChanges="True" ID="edControlType" runat="server" AllowNull="False" DataField="ControlType" />
<px:PXCheckBox ID="chkIsInternal" runat="server" DataField="IsInternal" />
<px:PXCheckBox ID="chkContainsPersonalData" runat="server" DataField="ContainsPersonalData" />
<px:PXTextEdit ID="edEntryMask" runat="server" DataField="EntryMask" />
<px:PXTextEdit ID="edRegExp" runat="server" DataField="RegExp" />
<px:PXSelector ID="SchemaObject" runat="server" DataField="ObjectName" AutoRefresh="True" CommitChanges="true" />
<px:PXDropDown ID="SchemaField" runat="server" DataField="FieldName" AutoRefresh="True" CommitChanges="True" />
<px:PXDropDown ID="edRegExpMultiSelect" runat="server" AllowMultiSelect="true" DataField="UsrSchemaField" CommitChanges="True"/>
</Template>
</px:PXFormView>
</asp:Content>
Having the field value disappear just means that the custom field was not correctly implemented. When the system can't select/persist a record or a field it disappears when control focus is lost.
The DAC field type appears to be wrong. Usually string list uses small codes of about 2 or 3 letters string with fixed size:
[PXDBString(3, IsFixed = true)]
Since you are setting the list dynamically you don't need to define null string values in the DAC:
[PXStringList]
You need to make sure that your event is always providing the expected code values. This can be checked by removing the conditions and using constants for the SetList method call:
https://stackoverflow.com/a/38089639/7376238
Maybe you missed some steps like creating the field in the database table. You can test with an unbound PXString field instead of a PXDBString like in this example to see if that's the issue:
https://stackoverflow.com/a/49907964/7376238
Thanks for the help, I solved the problem by replacing "e.Row" with "null" in this line
before:
PXStringListAttribute.SetList<KNRWCSAttributeExt.usrSchemaField>(e.Cache, e.Row, fields, fields);
after:
PXStringListAttribute.SetList<KNRWCSAttributeExt.usrSchemaField>(e.Cache, null, fields, fields);
Related
Problem #1
I have a Form with a split panel with a tree view on the left side and a grid on the right side.
The tree view is displaying itemClassCD. When I select an item in the tree, the current selection is always the same itemClassCd (the first entry), or null. The code view from the Tree is as follows "Tree.Current.ItemClassCD".
Form with Tree and Grid
Problem#2
The second issue is related to the display of the tree nodes.
They are showing a "+" sign and they will keep opening if I press the sign.
Node Issue
**This is what I have tried.
**
<%# Page Language="C#" MasterPageFile="~/MasterPages/FormDetail.master" AutoEventWireup="true" ValidateRequest="false" CodeFile="SG302010.aspx.cs" Inherits="Page_SG302010" Title="Untitled Page" %>
<%# MasterType VirtualPath="~/MasterPages/FormDetail.master" %>
<asp:Content ID="cont1" ContentPlaceHolderID="phDS" Runat="Server">
<script language="javascript" type="text/javascript">
function showTreeChanged(owner, args)
{
var visible = owner.getValue();
if (window['px_alls'] && px_alls["sp1"]) px_alls["sp1"].setDisabledPanel(visible ? 0 : 1);
}
function showTreeChk(e)
{
if (!loaded)
{
var px = __px_alls(this);
var TreeView = px_alls["chkShowTree"];
setTimeout(function ()
{
if (window['px_alls'] && px_alls["chkShowTree"] && px_alls["sp1"])
{
TreeView = px_alls["chkShowTree"];
px_alls["sp1"].setDisabledPanel(TreeView.getValue() ? 0 : 1);
}
loaded = true;
}, 1);
}
}
function showTreeLoad(e)
{
if (window['__px_alls'])
{
var pxs = __px_alls(this);
if (pxs)
{
setTimeout(function ()
{
var frm = pxs["form"];
if (frm) frm.events.addEventHandler("afterRepaint", showTreeChk);
}, 100);
}
}
}
var loaded = false;
window.addEventListener("load", showTreeLoad);
</script>
<px:PXDataSource EnableAttributes="True" ID="ds" Width="100%" runat="server" PrimaryView="Filter"
TypeName="ISGoalSetting.SGForecastEntry" Visible="True" PageLoadBehavior="PopulateSavedValues">
<CallbackCommands>
<px:PXDSCallbackCommand Name="Save" CommitChanges="True" RepaintControls="All" RepaintControlsIDs="grid" />
<px:PXDSCallbackCommand Name="distribute" Visible="False" CommitChanges="True" DependOnGrid="grid"
RepaintControls="Bound" />
<px:PXDSCallbackCommand Name="distributeOK" Visible="False" CommitChanges="True"
DependOnGrid="grid" />
<px:PXDSCallbackCommand CommitChanges="True" Visible="False" Name="preload" DependOnGrid="grid" />
<px:PXDSCallbackCommand CommitChanges="True" Name="showPreload" />
<px:PXDSCallbackCommand CommitChanges="True" Name="wNext" />
<px:PXDSCallbackCommand CommitChanges="True" Name="showManage" />
<px:PXDSCallbackCommand Name="manageOK" Visible="False" CommitChanges="True"/>
</CallbackCommands>
<DataTrees>
<px:PXTreeDataMember TreeView="Tree" TreeKeys="ItemClassID" ></px:PXTreeDataMember>
</DataTrees>
</px:PXDataSource>
</asp:Content>
<asp:Content ID="cont2" ContentPlaceHolderID="phF" Runat="Server">
<px:PXFormView ID="form" runat="server" Width="100%" DataMember="Filter" Caption="Forecast Filter"
LinkIndicator="True" BPEventsIndicator="True" DataSourceID="ds">
<Template>
<px:PXLayoutRule runat="server" ID="CstPXLayoutRule1" StartColumn="True" LabelsWidth="SM"
ControlSize="M" ></px:PXLayoutRule>
<px:PXSelector CommitChanges="True" ID="edBranchID" runat="server" DataField="BranchID"
DataSourceID="ds" ></px:PXSelector>
<px:PXSelector CommitChanges="True" ID="edFinYear" runat="server" DataField="FinYear"
DataSourceID="ds" AutoRefresh="True" ></px:PXSelector>
<px:PXCheckBox CommitChanges="True" ID="chkShowTree" runat="server" DataField="ShowTree">
<ClientEvents ValueChanged="showTreeChanged" />
</px:PXCheckBox>
</Template>
<CallbackCommands>
<Save PostData="Page" RepaintControls="All" RepaintControlsIDs="grid, tree" ></Save>
</CallbackCommands>
</px:PXFormView>
</asp:Content>
<asp:Content ID="cont3" ContentPlaceHolderID="phG" Runat="Server">
<px:PXSplitContainer runat="server" ID="sp1" SplitterPosition="220" CollapseDirection="Panel1"
Panel1MinSize="1" DisabledPanel="Panel1">
<AutoSize Enabled="true" Container="Window" />
<Template1>
<px:PXTreeView ID="tree" runat="server" PopulateOnDemand="True" ExpandDepth="1" DataSourceID="ds"
ShowRootNode="false" SelectFirstNode="true" >
<AutoCallBack Target="grid" Command="Refresh" />
<Images>
<ParentImages Normal="tree#Folder" Selected="tree#FolderS" />
<LeafImages Normal="tree#Folder" Selected="tree#FolderS" />
</Images>
<DataBindings>
<px:PXTreeItemBinding DataMember="Tree" TextField="ItemClassCD" ValueField="ItemClassID" ></px:PXTreeItemBinding>
</DataBindings>
<AutoSize Enabled="True" />
</px:PXTreeView>
</Template1>
<Template2>
<px:PXGrid ID="grid" runat="server" DataSourceID="ds" Width="100%" Height="150px" SkinID="Details" Caption="Forecast Details"
SyncPosition="True">
<AutoCallBack Command="Refresh" Target="form" ActiveBehavior="True">
<Behavior RepaintControlsIDs="ds" BlockPage="True" CommitChanges="True" ></Behavior>
</AutoCallBack>
<Levels>
<px:PXGridLevel DataMember="ForecastArticles">
<Columns>
<px:PXGridColumn DataField="BranchID" Width="140" ></px:PXGridColumn>
<px:PXGridColumn DataField="GoalType" Width="140" ></px:PXGridColumn>
<px:PXGridColumn DataField="ItemClass" Width="120" ></px:PXGridColumn>
<px:PXGridColumn DataField="Month" Width="90" ></px:PXGridColumn>
<px:PXGridColumn DataField="Goal" Width="100" ></px:PXGridColumn></Columns>
</px:PXGridLevel>
</Levels>
<AutoSize Container="Window" Enabled="True" MinHeight="150" ></AutoSize>
<ActionBar >
</ActionBar>
<Mode AllowUpload="True" /></px:PXGrid>
</Template2>
</px:PXSplitContainer>
</asp:Content>
public class SGForecastEntry : PXGraph<SGForecastEntry>
{
#region Actions
public PXSave<SGForecastFilter> Save;
public PXCancel<SGForecastFilter> Cancel;
public PXDelete<SGForecastFilter> Delete;
public PXAction<SGForecastFilter> First;
public PXAction<SGForecastFilter> Prev;
public PXAction<SGForecastFilter> Next;
public PXAction<SGForecastFilter> WNext;
public PXAction<SGForecastFilter> Last;
public PXAction<SGForecastFilter> ShowPreload;
public PXAction<SGForecastFilter> Preload;
public PXAction<SGForecastFilter> Distribute;
public PXAction<SGForecastFilter> DistributeOK;
public PXAction<SGForecastFilter> ShowManage;
public PXAction<SGForecastFilter> ManageOK;
#endregion
#region Selects
public PXFilter<SGForecastFilter> Filter;
public SelectFrom<INItemClass>.OrderBy<INItemClass.itemClassCD.Asc>.View Tree;
public SelectFrom<INItemClass>.
Where<INItemClass.itemClassID.IsEqual<INItemClass.itemClassID.FromCurrent>>.View CurrentNode;
/*Everything*/
[PXImport(typeof(ISSGForecast))]
public SelectFrom<ISSGForecast>.
OrderBy<Asc<ISSGForecast.itemClass>>.View ForecastArticles;
#endregion
protected bool suppressIDs;
public override IEnumerable ExecuteSelect(string viewName, object[] parameters, object[] searches, string[] sortcolumns, bool[] descendings, PXFilterRow[] filters, ref int startRow, int maximumRows, ref int totalRows)
{
IEnumerable ret = base.ExecuteSelect(viewName, parameters, searches, sortcolumns, descendings, filters, ref startRow, maximumRows, ref totalRows);
suppressIDs = viewName == nameof(ForecastArticles);
CurrentSelected.ClassCD = Tree.Current?.ItemClassCD;
return ret;
}
private SelectedClass CurrentSelected
{
get
{
PXCache cache = this.Caches[typeof(SelectedClass)];
if (cache.Current == null)
{
cache.Insert();
cache.IsDirty = false;
}
return (SelectedClass)cache.Current;
}
}
[Serializable]
[PXHidden]
public partial class SGForecastFilter : IBqlTable
{
#region BranchID
public abstract class branchID : PX.Data.BQL.BqlInt.Field<branchID> { }
[Branch(Required = true)]
public virtual int? BranchID { get; set; }
#endregion
#region FinYear
public abstract class finYear : PX.Data.BQL.BqlString.Field<finYear> { }
[PXUIField(DisplayName = "Financial Year", Required = true)]
[PXDBString(4)]
[GenericFinYearSelector(typeof(Search3<FinYear.year, OrderBy<Desc<FinYear.year>>>),null)]
public virtual String FinYear { get; set; }
#endregion
#region ShowTree
public abstract class showTree : PX.Data.BQL.BqlBool.Field<showTree> { }
[PXBool]
[PXUnboundDefault(true)]
[PXUIField(DisplayName = "Tree View")]
public virtual Boolean? ShowTree { get; set; }
#endregion
#region ItemClass
[PXDBString(10, IsUnicode = true, InputMask = "")]
[PXUIField(DisplayName = "Item Class", Visibility = PXUIVisibility.SelectorVisible)]
[PXSelector(typeof(Search<INItemClass.itemClassCD>))]
public virtual string ItemClass { get; set; }
public abstract class itemClass : PX.Data.BQL.BqlString.Field<itemClass> { }
#endregion
public short? Precision;
}
[Serializable]
[PXHidden]
public partial class SelectedClass : IBqlTable
{
#region ItemClass
[PXInt]
[PXSelector(typeof(Search<INItemClass.itemClassID>))]
public virtual int? ItemClass { get; set; }
public abstract class itemClass : PX.Data.BQL.BqlInt.Field<itemClass> { }
#endregion
#region ClassCD
[PXString]
[PXSelector(typeof(Search<INItemClass.itemClassCD>))]
public virtual string ClassCD { get; set; }
public abstract class classCD : PX.Data.BQL.BqlString.Field<classCD> { }
#endregion
}
}
I do not know why my code is not working or something might be missing.
I am trying to do is use PXAction to disable as specific field, when I compile and run this it my browser would just load into infinity.
Thank you guys!
Here is my code
DAC:
#region RadnomTest
[PXDBString(20, IsUnicode = true)]
[PXUIField(DisplayName = "Random Test")]
public virtual string RadnomTest { get; set; }
public abstract class radnomTest : BqlString.Field<radnomTest> { }
#endregion
GRAPH
#region Toggle Readonly
public PXAction<ClientProfileNames> ReadonlyToggle;
[PXButton(CommitChanges = true)]
[PXUIField(DisplayName = "Toggle Read-only")]
protected virtual void readonlyToggle(Events.RowSelected<ClientProfileNames> e)
{
var row = e.Row;
PXUIFieldAttribute.SetEnabled<ClientProfileNames.radnomTest>(e.Cache, row, true);
Actions.PressSave();
}
#endregion
PAGE
<asp:Content ID="cont1" ContentPlaceHolderID="phDS" Runat="Server">
<px:PXDataSource ID="ds" runat="server" Visible="True" Width="100%" PrimaryView="ClinetInfosMain" TypeName="OnlyForTesting.Graph.Profile.ClientProfileNamesMaint">
<CallbackCommands>
</CallbackCommands>
</px:PXDataSource>
</asp:Content>
<asp:Content ID="cont2" ContentPlaceHolderID="phF" Runat="Server">
<px:PXFormView ID="form" runat="server" DataSourceID="ds" Style="z-index: 100" Width="100%" DataMember="ClinetInfosMain" TabIndex="2900">
<Template>
<px:PXLayoutRule runat="server" StartRow="True" StartColumn="True"/>
<px:PXTextEdit ID="edRadnomTest" runat="server" AlreadyLocalized="False" DataField="RadnomTest" IsClientControl="True">
</px:PXTextEdit>
</Template>
<AutoSize Container="Window" Enabled="True" MinHeight="200" />
</px:PXFormView>
</asp:Content>
Field state should be set from the RowSelected event, and not as the result of an action such a button click.
If you need to set the enabled status based on the value of another field, I would recommend checking the PXUIEnabled attribute which will let you handle this in a declarative fashion: https://asiablog.acumatica.com/2016/11/pxuienabled-and-pxuirequired-attributes.html
I have created a PXGraphExtension on POLandedCostDocEntry. I have added a PXAction button. When the button is pressed I show a popup panel to ask the user for a landed cost code.
The problem is that the PXSelector ignores whatever I enter into the field and resets to APPLE (or whatever Landed Cost Code is alphabetically first). If I use the Selector to choose a different code, the code I select is visible for a moment and then immediately replaced with APPLE again.
The ASPX for the popup dialog is as follows:
<px:PXSmartPanel runat="server" ID="PanelAskForLCCode" LoadOnDemand="True" AutoRepaint="True" Key="LandedCostCodeSelection" CaptionVisible="True" Caption="Select Landed Cost Code" AcceptButtonID="CstButton4" CancelButtonID="CstButton5">
<px:PXPanel runat="server" ID="CstPanel9">
<px:PXFormView runat="server" ID="CstFormView10" SkinID="Transparent" Width="100%" SyncPosition="True" DataMember="LandedCostCodeSelection" DataSourceID="ds">
<Template>
<px:PXSelector runat="server" ID="CstPXSelector11" DataField="LandedCostCodeID" CommitChanges="True" DataSourceID="ds">
</px:PXSelector>
</Template>
</px:PXFormView>
</px:PXPanel>
<px:PXPanel runat="server" ID="LandedCostCodeSelectionButtons" SkinID="Buttons">
<px:PXButton runat="server" ID="CstButton4" DialogResult="OK" Text="OK" />
<px:PXButton runat="server" ID="CstButton5" DialogResult="Cancel" Text="Cancel" />
</px:PXPanel></px:PXSmartPanel>
The code for the view that I'm referencing in the dialog is:
public PXSelect<LandedCostCode> LandedCostCodeSelection;
The code that I'm using to call the dialog is:
if (LandedCostCodeSelection.AskExt() == WebDialogResult.OK)
{
//rest of code here
}
What am I missing to allow the user to select or type a different Landed Cost Code?
Edit 1:
I have changed the code for the view that I'm referencing in the dialog to:
public PXFilter<LandedCostCode> LandedCostCodeSelection;
My aspx now looks like this:
<px:PXSmartPanel runat="server" ID="PanelAskForLCCode" Key="LandedCostCodeSelection" CaptionVisible="True" Caption="Select Landed Cost Code" AcceptButtonID="CstButton4" CancelButtonID="CstButton5" Width="300px" AutoRepaint="True" LoadOnDemand="True">
<px:PXFormView runat="server" ID="CstFormView18" CaptionVisible="False" Caption="LC Code Selection" DataSourceID="ds" DataMember="LandedCostCodeSelection">
<Template>
<px:PXLayoutRule runat="server" ID="CstPXLayoutRule19" StartColumn="True" ControlSize="XM" LabelsWidth="S"/>
<px:PXSelector runat="server" ID="CstPXSelector20" DataField="LandedCostCodeID" CommitChanges="True" DataSourceID="ds" DataMember="LandedCostCodeSelection"/>
</Template>
<CallbackCommands>
<Search CommitChanges="True"/>
</CallbackCommands>
</px:PXFormView>
<px:PXPanel runat="server" ID="LandedCostCodeSelectionButtons" SkinID="Buttons">
<px:PXButton runat="server" ID="CstButton4" DialogResult="OK" Text="OK"/>
<px:PXButton runat="server" ID="CstButton5" DialogResult="Cancel" Text="Cancel"/>
</px:PXPanel>
</px:PXSmartPanel>
I'm calling the dialog as follows:
if (LandedCostCodeSelection.AskExt((graph, view) =>
{
LandedCostCodeSelection.Cache.Clear();
},true) == WebDialogResult.OK)
{
}
I notice that when I click on the selector button and pick a row from the selector (which briefly returns a value to the field which is then overwritten right away) when I click on the selector button again, the selector has remembered the record I last selected.
Finally, if I invoke the dialog as follows:
if (LandedCostCodeSelection.AskExt((graph, view) =>
{
LandedCostCodeSelection.Cache.Clear();
LandedCostCodeSelection.Current.LandedCostCodeID = "XYZ";
},true) == WebDialogResult.OK)
{
}
Then the field is populated with XYZ and if I click OK I can reference the value of XYZ. (But if I use the selector, then the value is cleared and cannot be accessed again.)
The problem relies in the definition of the DataView and the DAC used. I have reproduced the issue and this is what I've changed to make it work:
Use a new custom DAC as a source for your view. Note that the field is not bound and is not key (does not have IsKey = true, as in LandedCostCode.LandedCostCodeID:
[Serializable]
[PXHidden]
public partial class LandedCostCodeFilter: IBqlTable
{
#region LandedCostCodeID
public abstract class landedCostCodeID : PX.Data.BQL.BqlString.Field<landedCostCodeID> { }
[PXString(15, IsUnicode = true)]
//[PXUnboudDefault("APPLE")] //optional, to preselect a value
[PXUIField(DisplayName = "Landed Cost Code",Visibility=PXUIVisibility.SelectorVisible)]
[PXSelector(typeof(Search<LandedCostCode.landedCostCodeID>))]
public virtual String LandedCostCodeID {get; set}
#endregion
}
Change the DataView definition, using a PXFilter instead of PXSelect and use the new DAC
public PXFilter<LandedCostCodeFilter> LandedCostCodeSelection;
Correct that and your dialog should work.
Obs.
If you want to have a value pre-selected when you open the dialog, add [PXUnboudDefault("APPLE")] to the field in the DAC
Not sure how does your button definition look like, but here is what it should be:
public PXAction<POLandedCostDoc> SelectLandedCost;
[PXButton]
[PXUIField(DisplayName = "Select Landed Cost Code", MapEnableRights = PXCacheRights.Delete, MapViewRights = PXCacheRights.Delete)]
protected void selectLandedCost()
{
if(LandedCostCodeSelection.AskExt(true) != WebDialogResult.OK) return;
// do some stuff here
}
Also, my aspx code:
<px:PXSmartPanel runat="server" ID="PanelAskForLCCode" Caption="Select Landed Cost Code" CaptionVisible="True" Key="LandedCostCodeSelection">
<px:PXFormView runat="server" ID="CstFormView2" DataMember="LandedCostCodeSelection" SkinID="Transparent" DataSourceID="ds" Height="100%" Width="100%">
<Template>
<px:PXLayoutRule runat="server" ID="CstPXLayoutRule3" StartColumn="True" />
<px:PXSelector runat="server" ID="CstPXSelector4" DataField="LandedCostCodeID" CommitChanges="True" AutoRefresh="True" />
<px:PXPanel runat="server" ID="LandedCostCodeSelectionButtons" SkinID="Buttons">
<px:PXButton runat="server" ID="CstButton6" DialogResult="OK" Text="OK" />
<px:PXButton runat="server" ID="CstButton7" DialogResult="Cancel" Text="Cancel" /></px:PXPanel></Template></px:PXFormView></px:PXSmartPanel>
we have requirement to update the selected value in pop up screen in custom screen grid.
can anyone help me on this.
Thanks.
I have worked on the same functionality in other projects. The below code will help you. Please let me know if you get any issues.
Action Button Code
public PXAction<SOAmazonSetup> GetSchema;
[PXButton]
[PXUIField(DisplayName = SOMessages.getSchema, MapEnableRights = PXCacheRights.Select, MapViewRights = PXCacheRights.Select, Enabled = true)]
protected virtual IEnumerable getSchema(PXAdapter adapter)
{
if (setupview.Current != null)
{
if (schemaView.AskExt() == WebDialogResult.OK && !string.IsNullOrEmpty(schemaView.Current.AmazonOrderID))
{
bool isgetSchema = true;
SOSchemaFileDetails objSchemaFileDetails = PXSelectJoin<SOSchemaFileDetails, InnerJoin<SOAmazonSetup, On<SOSchemaFileDetails.integrationID,
Equal<SOAmazonSetup.integrationID>>>, Where<SOAmazonSetup.integrationID, Equal<Current<SOAmazonSetup.integrationID>>>>.Select(this);
if (objSchemaFileDetails != null)
{
if (msgView.Ask(schemaView.Current, SOMessages.getSchema, SOMessages.warningMsg, MessageButtons.YesNo, MessageIcon.Warning) == WebDialogResult.No)
{
isgetSchema = false;
}
}
if (isgetSchema)
{
// get needed information in local variables
string sAmazonOrderID = schemaView.Current.AmazonOrderID;
string sIntegrationID = setupview.Current.IntegrationID;
PXLongOperation.StartOperation(this, delegate ()
{
//Create Instance
SOAmazonSetupMaint setupGraph = PXGraph.CreateInstance<SOAmazonSetupMaint>();
setupGraph.setupview.Current = setupGraph.setupview.Search<SOAmazonSetup.integrationID>(sIntegrationID);
SOHelper.GetSchemaFromAmazon(setupGraph, clientOrder, sAmazonOrderID);
DynamicSchema.ReloadSchema(setupGraph, sIntegrationID);
});
}
}
else
{
throw new Exception(SOMessages.AmwOrderCannotbeEmpty);
}
}
return adapter.Get();
}
SmartPanel code:
<px:PXSmartPanel ID="AMpnlGetSchema" runat="server" Caption="Get Schema"
CaptionVisible="true" DesignView="Hidden" LoadOnDemand="true" Key="schemaView" CreateOnDemand="false" AutoCallBack-Enabled="true"
AutoCallBack-Target="formGetSchema" AutoCallBack-Command="Refresh" CallBackMode-CommitChanges="True" CallBackMode-PostData="Page"
AcceptButtonID="btnOK" Width=" 250px">
<px:PXFormView ID="AMformGetSchema" runat="server" DataSourceID="ds" Style="z-index: 100" Width="100%" CaptionVisible="False"
DataMember="schemaView">
<ContentStyle BackColor="Transparent" BorderStyle="None" />
<Template>
<px:PXLayoutRule ID="AMPXLayoutRuleAmazonAPISettings" StartColumn="true" runat="server" ControlSize="M" />
<px:PXTextEdit CommitChanges="True" runat="server" ID="AMCstPXTextEditAmazonOrderID" DataField="AmazonOrderID"></px:PXTextEdit>
</Template>
</px:PXFormView>
<px:PXPanel ID="AMpnlOK" runat="server" SkinID="Buttons">
<px:PXButton ID="btnOK" runat="server" DialogResult="OK" Text="OK">
<AutoCallBack Target="formGetSchema" Command="Save" />
</px:PXButton>
</px:PXPanel>
</px:PXSmartPanel>
I am trying to add a detail grid tied to the selected sales category on the Sales Category screen (IN204060)
Created a DAC that holds the grid data:
public class INCategoryFilesCTC : IBqlTable
{
#region CategoryID
[PXDBInt(IsKey = true)]
[PXUIField(DisplayName = "Category ID")]
public virtual int? CategoryID { get; set; }
public abstract class categoryID : IBqlField { }
#endregion
#region Type
[PXDBString(1, IsFixed = true, IsUnicode = true, InputMask = "")]
[PXUIField(DisplayName = "Type")]
public virtual string Type { get; set; }
public abstract class type : IBqlField { }
#endregion
#region NoteID
[PXNote()]
[PXUIField(DisplayName = "Price Source")]
public virtual Guid? NoteID { get; set; }
public abstract class noteID : IBqlField { }
#endregion
#region Uploaded
[PXDBDate()]
[PXUIField(DisplayName = "Uploaded")]
public virtual DateTime? Uploaded { get; set; }
public abstract class uploaded : IBqlField { }
#endregion
#region FileName
[PXDBString(50, IsFixed = true, IsUnicode = true, InputMask = "")]
[PXUIField(DisplayName = "File Name")]
public virtual string FileName { get; set; }
public abstract class fileName : IBqlField { }
#endregion
}
Then added a data view delegate select (was having issues with Current<> due to the non standard selects for the rest of the graph data)
public PXSelect<INCategoryFilesCTC> CategoryFiles;
protected virtual IEnumerable categoryFiles()
{
var cache = Base.Caches[typeof(INCategoryFilesCTC)];
cache.AllowInsert = true;
cache.AllowUpdate = true;
cache.AllowDelete = true;
var select = PXSelect<INCategoryFilesCTC,
Where<INCategoryFilesCTC.categoryID,
Equal<Required<INCategoryFilesCTC.categoryID>>>>.Select(Base,Base.Folders.Current.CategoryID).FirstTableItems;
foreach (INCategoryFilesCTC item in select)
{
cache.SetStatus(item,PXEntryStatus.Held);
}
return cache.Cached;
}
The grid lives inside of 1/2 of a split container, and inside a tab. Search for ID="WebFiles" ( is the half it lives in, figured I wouldn't drown you guys with aspx code, if you want the rest let me know)
<Template2>
<px:PXFormView ID="form" runat="server" DataSourceID="ds" DataMember="CurrentCategory"
Caption="Category Info" Width="100%">
<Template>
<px:PXLayoutRule ID="PXLayoutRule1" runat="server" StartColumn="True" LabelsWidth="S" ControlSize="SM" />
<px:PXTextEdit ID="edDescription" runat="server" DataField="Description" CommitChanges="True" />
<px:PXLayoutRule ID="PXLayoutRule2" runat="server" StartColumn="True" LabelsWidth="S" ControlSize="SM" />
<px:PXTreeSelector ID="edParentID" runat="server" DataField="ParentID" ShowRootNode="False"
TreeDataMember="ParentFolders" TreeDataSourceID="ds" AutoRefresh="True" ExpandDepth="1"
SyncPosition="True" DataMember="ParentFolders" AutoRepaint="True" CommitChanges="True" KeepPosition="True">
<DataBindings>
<px:PXTreeItemBinding DataMember="ParentFolders" TextField="Description" ValueField="CategoryID" />
</DataBindings>
</px:PXTreeSelector>
<px:PXLayoutRule ID="PXLayoutRule3" runat="server" StartColumn="True" LabelsWidth="S" ControlSize="SM" />
</Template>
</px:PXFormView>
<px:PXTab runat="server" >
<Items>
<px:PXTabItem Text="Category Members">
<Template>
<px:PXGrid ID="gridMembers" runat="server" ActionsPosition="Top" Width="100%"
SkinID="Details" CaptionVisible="true" SyncPosition="True"
AutoRepaint="True" AdjustPageSize="Auto">
<AutoSize Enabled="True" Container="Parent"/>
<Mode InitNewRow="True"></Mode>
<Levels>
<px:PXGridLevel DataMember="Members">
<Columns>
<px:PXGridColumn AllowCheckAll="True" AllowNull="False" DataField="CategorySelected" TextAlign="Center"
Type="CheckBox" Width="26px" />
<px:PXGridColumn DataField="InventoryID" CommitChanges="true" Width="140px" LinkCommand="viewDetails"/>
<px:PXGridColumn DataField="InventoryItem__Descr" Width="200px"/>
<px:PXGridColumn DataField="InventoryItem__ItemClassID" Width="140px"/>
<px:PXGridColumn AllowNull="False" DataField="InventoryItem__ItemStatus" RenderEditorText="True" Width="100px"/>
</Columns>
</px:PXGridLevel>
</Levels>
<ActionBar>
<Actions>
<Search Enabled="False" />
<EditRecord Enabled="False" />
<NoteShow Enabled="False" />
<FilterShow Enabled="False" />
<FilterSet Enabled="False" />
<ExportExcel Enabled="False" />
</Actions>
<CustomItems>
<px:PXToolBarButton Tooltip="Copy Selected Inventory Items" DisplayStyle="Image">
<AutoCallBack Command="Copy" Enabled="True" Target="ds" />
<Images Normal="main#Copy" />
</px:PXToolBarButton>
<px:PXToolBarButton Tooltip="Cut Selected Inventory Items" DisplayStyle="Image">
<AutoCallBack Command="Cut" Enabled="True" Target="ds" />
<Images Normal="main#Cut" />
</px:PXToolBarButton>
<px:PXToolBarButton Tooltip="Paste Inventory Items from Buffer" DisplayStyle="Image">
<AutoCallBack Command="Paste" Enabled="True" Target="ds" />
<Images Normal="main#Paste" />
</px:PXToolBarButton>
<px:PXToolBarButton>
<AutoCallBack Command="AddItemsbyClass" Target="ds" />
</px:PXToolBarButton>
<px:PXToolBarButton Text="Inventory Details" Key="cmdviewDetails" Visible="False">
<AutoCallBack Command="viewDetails" Target="ds" />
</px:PXToolBarButton>
</CustomItems>
</ActionBar>
</px:PXGrid>
</Template>
</px:PXTabItem>
<px:PXTabItem Text="Website Media">
<template>
<px:PXFormView ID="WebForm" runat="server" DataSourceID="ds" DataMember="CurrentCategory">
<Template>
<px:PxTextEdit ID="txtVideoURL" runat="server" DataField="CTCVideoURL" />
<px:PxTextEdit ID="txtCategoryDesc" runat="server" DataField="CTCCategoryDesc" />
</Template>
</px:PXFormView>
<px:PXGrid ID="WebFiles" runat="server" FilesIndicator="True" Height="300px" Width="100%" DataSourceID="ds">
<Levels>
<px:PXGridLevel DataMember="CategoryFiles" DataKeyNames="CategoryID">
<Columns>
<px:PXGridColumn DataField="CategoryID" />
<px:PXGridColumn DataField="Type" />
<px:PXGridColumn DataField="Filename" />
<px:PXGridColumn DataField="Uploaded"/>
</Columns>
</px:PXGridLevel>
</Levels>
<ActionBar>
<Actions>
<Delete Enabled="True" />
<AddNew Enabled="True" />
</Actions></ActionBar>
</px:PXGrid>
</template>
</px:PXTabItem>
</Items>
</px:PXTab>
</Template2>
When I select a tree element, if there are records that would show up in my custom table (tree element categoryID = grid record categoryID) I get the following error:
Error: an invalid argument has been specified
Parameter name selectParent
Absolutely nothing comes up in trace, and nothing comes up during debugging, so I am at a bit of a loss.
A few things:
The error goes away when I comment out my custom PXGrid, and I can use the screen normally even with the tabs and groups i have added
The error does not go away if i comment out the PXParent and PXDBDefault attributes on the grids CategoryID DAC Field
If there is no detail record for the selected tree choice, there is no error. If I make a record and save it, the error appears (with the inserted record now showing in the grid, and a saved detail record in the database table)
This lends me to believe something is happening on the select of the detail records. Any advice?
Thanks
-Kyle
OK, this turned out to be more basic than I thought.. whoops. If you want to skip reading it turned out to be due to a simple key issue on the detail records
First off, I removed the data view delegate, the "Current" Sales category ID was coming through fine
public PXSelect<INCategoryFilesCTC,
Where<INCategoryFilesCTC.categoryID,
Equal<Current<INCategory.categoryID>>>> CategoryFiles;
Second off, added the correct PXParent and PXDBdefault attributes for the master-detail link (on field CategoryID)
#region CategoryID
[PXDBInt(IsKey=true)]
[PXParent(typeof(Select<INCategory, Where<INCategory.categoryID, Equal<Current<INCategory.categoryID>>>>))]
[PXDBDefault(typeof(INCategory.categoryID))]
public virtual int? CategoryID { get; set; }
public abstract class categoryID : IBqlField { }
#endregion
But lastly I added a Row# style column that used attribute [PXLineNbr]
#region CatFileKey
[PXDBInt(IsKey=true)]
[PXLineNbr(typeof(INCTC001INCategory.ctcPrevFileNumber))]
public virtual int? CatFileKey { get; set; }
public abstract class carFileKey : IBqlField { }
#endregion
And having this second key fixed my problem immediately
So all in all an error that I thought was due to some difficult customization was really because of some extremely basic thing ha ha.. hopefully this post prevents people from forgetting the same thing