在Acumatica中,我想为“物料清单”屏幕创建一个TreeView. This is what the screen currently looks like,我需要帮助填充网格左侧的树.我希望树的最高值是BOM项目,然后构成该项目的材料将在每个项目的材料下方打开.到目前为止,这是我的代码.
<DataTrees>
<px:PXTreeDataMember TreeKeys="BOMID" TreeView="Nodes" />
<px:PXTreeDataMember TreeView="_AMBOMTree_Tree_" TreeKeys="OberNbr" />
<px:PXTreeDataMember TreeKeys="Key" TreeView="CacheTree" />
<px:PXTreeDataMember TreeKeys="Key" TreeView="EntityItems" />
</DataTrees>
这是针对数据树本身的.
<px:PXTreeSelector CommitChanges="True" SuppressLabel="False" ID="edGraphType" runat="server" DataField="GraphType" PopulateOnDemand="True"
ShowRootNode="False" TreeDataSourceID="ds" TreeDataMember="CacheTree" InitialExpandLevel="0" MinDropWidth="297" MaxDropWidth="500"
TextField="Name" Size="XL">
<Images>
<ParentImages Normal="tree@Folder" Selected="tree@FolderS" />
<LeafImages Normal="tree@Screen" Selected="tree@Screen" />
</Images>
<DataBindings>
<px:PXTreeItemBinding DataMember="CacheTree" TextField="Name" ValueField="SubKey" ImageUrlField="Icon" />
</DataBindings>
</px:PXTreeSelector>
这是TreeSelector.现在,我从另一个屏幕上拉出了它,并想知道这是如何工作的.由于我希望该项目显示在顶层,因此转到构成该项目的材料.如果要选择一个项目,我希望填充网格.我知道DataField = GraphType是不正确的,因为它是从另一个屏幕中拉出的,但是我不知道应该在这里的值.
<px:PXTreeView ID="tree" runat="server" DataSourceID="ds" Height="500px" PopulateOnDemand="True" ShowRootNode="False"
ExpandDepth="1" AutoRepaint="true" Caption="Tree" AllowCollapse="true" PreserveExpanded="true">
<ToolBarItems>
<px:PXToolBarButton Tooltip="Reload Tree" ImageKey="Refresh">
<AutoCallBack Target="tree" Command="Refresh" />
</px:PXToolBarButton>
</ToolBarItems>
<AutoCallBack Target="grid" Command="Refresh" ActiveBehavior="True">
<Behavior RepaintControlsIDs="gridMatl" />
<Behavior RepaintControlsIDs="gridStep" />
<Behavior RepaintControlsIDs="gridTool" />
<Behavior RepaintControlsIDs="gridOvhd" />
</AutoCallBack>
<AutoSize Enabled="True" MinHeight="300" />
<DataBindings>
<px:PXTreeItemBinding DataMember="Nodes" TextField="Name" ValueField="AssignmentRouteID" ImageUrlField="Icon" />
</DataBindings>
</px:PXTreeView>
这就是树视图本身.
如果有人可以帮助我编写这棵树,那将是不错的选择,或者至少可以指出我的正确方向.
解决方法:
要在Acumatica中添加数据树,需要做以下三件事:
>在ASPX页面中,在PXDataSource中声明PXDataTreeMember:
<px:PXDataSource ID="ds" runat="server" Visible="True" PrimaryView="Document" SuspendUnloading="False" TypeName="PX.TreeDemo.TreeEntry">
<CallbackCommands>
<px:PXDSCallbackCommand CommitChanges="True" Name="MyAction" />
<px:PXDSCallbackCommand CommitChanges="True" Name="MyOtherAction" Visible="False" />
<px:PXDSCallbackCommand CommitChanges="True" Name="SomeOtherOtherAction" Visible="False" />
</CallbackCommands>
<DataTrees>
<px:PXTreeDataMember TreeView="Nodes" TreeKeys="NodeID" />
</DataTrees>
</px:PXDataSource>
>添加带有链接的FormView的PXTreeView(通常带有PXSplitContainer),它将显示选定的记录.
<px:PXSplitContainer runat="server" ID="sp1" SplitterPosition="300">
<AutoSize Enabled="true" Container="Window" />
<Template1>
<px:PXTreeView ID="tree" runat="server" DataSourceID="ds" Height="180px"
ShowRootNode="False" AllowCollapse="False" Caption="Tree Demo" AutoRepaint="True"
SyncPosition="True" ExpandDepth="4" DataMember="Nodes" KeepPosition="True"
SyncPositionWithGraph="True" PreserveExpanded="True" PopulateOnDemand="true" SelectFirstNode="True">
<ToolBarItems>
<px:PXToolBarButton Text="Add Tree Node" Tooltip="Add Tree Node">
<AutoCallBack Command="AddNode" Enabled="True" Target="ds" />
<Images Normal="main@AddNew" />
</px:PXToolBarButton>
<px:PXToolBarButton Text="Delete Tree Node" Tooltip="Delete Tree Node">
<AutoCallBack Command="DeleteNode" Enabled="True" Target="ds" />
<Images Normal="main@Remove" />
</px:PXToolBarButton>
</ToolBarItems>
<AutoCallBack Target="formTree" Command="Refresh" Enabled="True" />
<DataBindings>
<px:PXTreeItemBinding DataMember="Nodes" TextField="DisplayName" ValueField="NodeID" />
</DataBindings>
<AutoSize Enabled="True" />
</px:PXTreeView>
</Template1>
<Template2>
<px:PXFormView ID="formTree" runat="server" DataSourceID="ds" DataMember="CurrentNode"
Caption="Node Info" Width="100%" >
<Template>
<px:PXLayoutRule ID="PXLayoutRule1" runat="server" StartColumn="True" LabelsWidth="S" ControlSize="SM" />
<px:PXSelector ID="edNodeID" runat="server" DataField="NodeID" CommitChanges="True" AutoRefresh="True" />
</Template>
</px:PXFormView>
</Template2>
</px:PXSplitContainer>
>创建数据视图,数据视图委托和树操作.
public PXSelect<TreeNode> Nodes;
public PXSelect<TreeNode,
Where<TreeNode.parentNodeID,
Equal<Optional<TreeNode.nodeID>>>> ChildNodes;
public PXSelect<TreeNode,
Where<TreeNode.nodeID,
Equal<Current<TreeNode.nodeID>>>> CurrentNode;
#endregion
#region Delegates
protected virtual IEnumerable nodes(
[PXInt]
int? nodeID
)
{
if (nodeID == null)
{
yield return new TreeNode()
{
ParentNodeID = 0,
NodeID = 0
};
}
else
{
foreach (TreeNode node in ChildNodes.Select(nodeID))
{
yield return node;
}
}
}
protected virtual IEnumerable currentNode()
{
if (Nodes.Current != null)
{
var isNotRoot = Nodes.Current.NodeID != 0;
//Situation where we would want to limit the recursion to one
AddNode.SetEnabled(!isNotRoot);
DeleteNode.SetEnabled(isNotRoot);
Caches[typeof(TreeNode)].AllowInsert = isNotRoot;
Caches[typeof(TreeNode)].AllowDelete = isNotRoot;
Caches[typeof(TreeNode)].AllowUpdate = isNotRoot;
foreach (TreeNode item in PXSelect<TreeNode,
Where<TreeNode.nodeID,
Equal<Required<TreeNode.nodeID>>>>.
Select(this, Nodes.Current.NodeID))
{
yield return item;
}
}
}
public PXAction<NodeSetup> AddNode;
[PXUIField(DisplayName = " ", MapEnableRights = PXCacheRights.Select, MapViewRights = PXCacheRights.Select, Enabled = true)]
[PXButton()]
public virtual IEnumerable addNode(PXAdapter adapter)
{
var selectedNode = Nodes.Current;
if (selectedNode.ParentNodeID == 0)
{
var inserted = (TreeNode)Caches[typeof(TreeNode)].Insert(new TreeNode
{
ParentNodeID = Nodes.Current.NodeID
});
inserted.TempChildID = inserted.NodeID;
inserted.TempParentID = inserted.ParentNodeID;
Nodes.Cache.ActiveRow = inserted;
}
return adapter.Get();
}
public PXAction<NodeSetup> DeleteNode;
[PXUIField(DisplayName = " ", MapEnableRights = PXCacheRights.Select, MapViewRights = PXCacheRights.Select, Enabled = true)]
[PXButton()]
public virtual IEnumerable deleteNode(PXAdapter adapter)
{
var selectedNode = Nodes.Current;
if(selectedNode.NodeID != 0)
{
if(selectedNode.ParentNodeID == 0)
{
var childrenNodes = ChildNodes
.Select(selectedNode.NodeID)
.Select(br => (TreeNode)br).ToList();
if (childrenNodes.Any())
{
if (Document.Ask(Messages.ValidationDeleteChildren, MessageButtons.YesNo) == WebDialogResult.Yes)
{
foreach(var childrenNode in childrenNodes)
{
Caches[typeof(TreeNode)].Delete(childrenNode);
}
Caches[typeof(TreeNode)].Delete(selectedNode);
}
}
else
{
Caches[typeof(TreeNode)].Delete(selectedNode);
}
}
else
{
Caches[typeof(TreeNode)].Delete(selectedNode);
}
}
return adapter.Get();
}
解决该问题的最简单方法通常是使用单个ID.因为您的对象不是全部相同(BOM / MATL / ETC),所以您需要能够从ID中找出它.我建议的解决方案是格式化NodeID,使其具有获取所需记录所需的所有信息(E.I. BOM-BM00001_MATL-INVIDANDOTHERKEYFIELD).这样,您将知道自己是哪个级别并返回合适的子级(在Dataview委托节点(int?nodeID)中).