CodeGo.net>为Acumatica创建TreeView

在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)中).

上一篇:使用HierarchicalDataTemplate的WPF MVVM TreeView无法更新


下一篇:c#-WPF弹出窗口中的控件有时无法接收输入