} // getLayout()

        /// <summary>
        /// Returns a layout for a property on a tab.
        /// If edit, be sure to supply a valid TabId.
        /// </summary>
        public NodeTypeLayout getLayout(CswEnumNbtLayoutType LayoutType, Int32 NodeTypeId, Int32 PropId, Int32 TabId, CswDateTime Date)
        {
            NodeTypeLayout ret = null;

            if (false == CswTools.IsDate(Date))
            {
                _CacheLayout(NodeTypeId);
                ret = _Cache[NodeTypeId].FirstOrDefault(Layout => Layout.LayoutType == LayoutType &&
                                                        Layout.PropId == PropId &&
                                                        (LayoutType != CswEnumNbtLayoutType.Edit || Layout.TabId == TabId));
            }
            else
            {
                string Sql = @"select * from " + CswNbtAuditTableAbbreviation.getAuditTableSql(_CswNbtMetaDataResources.CswNbtResources, "nodetype_layout", Date) +
                             "  where nodetypeid = " + NodeTypeId + " " +
                             "    and layouttype = '" + LayoutType.ToString() + "' " +
                             "    and nodetypepropid = " + PropId + " ";
                if (LayoutType == CswEnumNbtLayoutType.Edit)
                {
                    Sql += "      and nodetypetabsetid = " + TabId;
                }

                CswArbitrarySelect LayoutSelect = _CswNbtMetaDataResources.CswNbtResources.makeCswArbitrarySelect("getLayout_Audit_Select", Sql);
                DataTable          LayoutTable  = LayoutSelect.getTable();
                if (LayoutTable.Rows.Count > 0)
                {
                    ret = new NodeTypeLayout(LayoutTable.Rows[0]);
                }
            }
            return(ret);
        } // getLayout()
        /// <summary>
        /// Returns a dictionary of layout by tab
        /// </summary>
        public Dictionary <Int32, NodeTypeLayout> getLayout(CswEnumNbtLayoutType LayoutType, Int32 NodeTypeId, Int32 PropId, CswDateTime Date)
        {
            Dictionary <Int32, NodeTypeLayout> LayoutByTab = new Dictionary <Int32, NodeTypeLayout>();

            if (false == CswTools.IsDate(Date))
            {
                _CacheLayout(NodeTypeId);
                foreach (NodeTypeLayout Layout in _Cache[NodeTypeId].Where(Layout => Layout.LayoutType == LayoutType &&
                                                                           Layout.PropId == PropId))
                {
                    LayoutByTab[Layout.TabId] = Layout;
                }
            }
            else
            {
                string Sql = @"select * from " + CswNbtAuditTableAbbreviation.getAuditTableSql(_CswNbtMetaDataResources.CswNbtResources, "nodetype_layout", Date) +
                             "  where nodetypeid = " + NodeTypeId + " " +
                             "    and layouttype = '" + LayoutType.ToString() + "' " +
                             "    and nodetypepropid = " + PropId;
                CswArbitrarySelect LayoutSelect = _CswNbtMetaDataResources.CswNbtResources.makeCswArbitrarySelect("getLayout_Audit_Select", Sql);
                DataTable          LayoutTable  = LayoutSelect.getTable();
                foreach (DataRow LayoutRow in LayoutTable.Rows)
                {
                    NodeTypeLayout Layout = new NodeTypeLayout(LayoutRow);
                    LayoutByTab.Add(Layout.TabId, Layout);
                }
            }
            return(LayoutByTab);
        } // getLayout()
        } // updatePropLayout()

        public void updatePropLayout(CswEnumNbtLayoutType LayoutType, CswNbtMetaDataNodeTypeProp Prop, CswNbtMetaDataNodeTypeProp InsertAfterProp, bool DoMove)
        {
            bool Added = false;

            if (DoMove)
            {
                removePropFromLayout(LayoutType, Prop, Int32.MinValue);
            }
            if (InsertAfterProp != null)
            {
                Dictionary <Int32, NodeTypeLayout> InsertAfterPropLayouts = getLayout(LayoutType, InsertAfterProp, null);
                if (InsertAfterPropLayouts.Values.Count > 0)
                {
                    foreach (Int32 TabId in InsertAfterPropLayouts.Keys)
                    {
                        NodeTypeLayout InsertAfterPropLayout = InsertAfterPropLayouts[TabId];

                        // Make space for the new prop
                        CswTableUpdate LayoutUpdate = _CswNbtMetaDataResources.CswNbtResources.makeCswTableUpdate("makeSpaceForProp_Update", "nodetype_layout");
                        string         WhereClause  = "where layouttype = '" + LayoutType.ToString() + "' and nodetypeid = " + InsertAfterProp.NodeTypeId.ToString();
                        if (TabId != Int32.MinValue && LayoutType == CswEnumNbtLayoutType.Edit)
                        {
                            WhereClause += " and nodetypetabsetid = " + TabId.ToString();
                        }
                        DataTable LayoutTable = LayoutUpdate.getTable(WhereClause);

                        foreach (DataRow Row in LayoutTable.Rows)
                        {
                            if (CswConvert.ToInt32(Row["display_column"]) == InsertAfterPropLayout.DisplayColumn &&
                                CswConvert.ToInt32(Row["display_row"]) > InsertAfterPropLayout.DisplayRow)
                            {
                                Row["display_row"] = CswConvert.ToDbVal(CswConvert.ToInt32(Row["display_row"]) + 1);
                            }
                        }
                        LayoutUpdate.update(LayoutTable);

                        // Add new prop to the layout
                        updatePropLayout(LayoutType, Prop.NodeTypeId, Prop, false, TabId, InsertAfterPropLayout.DisplayRow + 1, InsertAfterPropLayout.DisplayColumn, InsertAfterPropLayout.TabGroup);
                        Added = true;
                    } // foreach( Int32 TabId in InsertAfterPropLayouts.Keys )
                }     // if( InsertAfterPropLayouts.Values.Count > 0 )
            }         // if( InsertAfterProp != null )

            if (false == Added)
            {
                // Just add it somewhere
                updatePropLayout(LayoutType, Prop.NodeTypeId, Prop, false, Prop.getNodeType().getFirstNodeTypeTab().TabId);
            }

            if (_Cache.ContainsKey(Prop.NodeTypeId))
            {
                _Cache.Remove(Prop.NodeTypeId);
            }
        } // updatePropLayout()
 private void _CacheLayout(Int32 NodeTypeId)
 {
     if (false == _Cache.ContainsKey(NodeTypeId))
     {
         // Cache every layout for this nodetype, for performance
         Collection <NodeTypeLayout> Layouts = new Collection <NodeTypeLayout>();
         CswTableSelect LayoutSelect         = _CswNbtMetaDataResources.CswNbtResources.makeCswTableSelect("getLayout_Select", "nodetype_layout");
         DataTable      LayoutTable          = LayoutSelect.getTable("where nodetypeid = " + NodeTypeId);
         foreach (DataRow LayoutRow in LayoutTable.Rows)
         {
             NodeTypeLayout Layout = new NodeTypeLayout(LayoutRow);
             Layouts.Add(Layout);
         }
         _Cache[NodeTypeId] = Layouts;
     }
 }