// generate column header tree from scratch
        void GenerateFullColumnHeader(Dictionary <RXClass, StringCollection> classPropertiesMap)
        {
            treeColumnHeader.Nodes.Clear();
            // First, we generate a "General" header which contains common properties that are scheduled across different classes.
            Dictionary <string, List <RXClass> > propertyClassesMap = classPropertiesMap.GroupClassesByProperty();

            if (propertyClassesMap.ContainsGeneralProperty())
            {
                propertyClassesMap.FilterOutSingleProperties();
                TreeNode headerNode = treeColumnHeader.Nodes.Add("General");
                GenerateColumnHeaderByProperty(propertyClassesMap, headerNode.Nodes);
            }

            Dictionary <RXClass, StringCollection> newClassPropertiesMap = classPropertiesMap.DeepClone();

            propertyClassesMap.FilterOutGeneralProperties(newClassPropertiesMap);

            foreach (RXClass objectType in newClassPropertiesMap.Keys)
            {
                if (newClassPropertiesMap[objectType].Count > 0)
                {
                    TreeNode headerNode = treeColumnHeader.Nodes.Add(ScheduleSample.GetDisplayName(objectType));
                    GenerateColumnHeaderByObjectType(objectType, newClassPropertiesMap[objectType], headerNode.Nodes);
                }
            }
            treeColumnHeader.ExpandAll();
        }
        // Fill the property tree with the property definition sets defined in the previous wizard sheet.
        void FillPropertyTree()
        {
            treeProperties.Nodes.Clear();
            // Add a "General" node which contains common properties that are scheduled across different classes.
            Dictionary <string, List <RXClass> > propertyClassesMap = runtimeData.classPropertiesMap.GroupClassesByProperty();

            if (propertyClassesMap.ContainsGeneralProperty())
            {
                TreeNode         headerNode        = treeProperties.Nodes.Add("General");
                StringCollection generalProperties = propertyClassesMap.GetGeneralPropertyNames();
                foreach (string propName in generalProperties)
                {
                    AddPropertyToNodeCollection(headerNode.Nodes, propertyClassesMap[propName], propName);
                }
            }
            // Now we add properties grouped by class
            Dictionary <RXClass, StringCollection> newClassPropertiesMap = runtimeData.classPropertiesMap.DeepClone();

            propertyClassesMap.FilterOutGeneralProperties(newClassPropertiesMap); // we only need the properties that are not shared across classes at this stage

            foreach (RXClass objectType in newClassPropertiesMap.Keys)
            {
                if (newClassPropertiesMap[objectType].Count == 0)
                {
                    continue;
                }

                TreeNode         newNode       = treeProperties.Nodes.Add(ScheduleSample.GetDisplayName(objectType));
                StringCollection propertyNames = newClassPropertiesMap[objectType];
                foreach (string propertyName in propertyNames)
                {
                    AddPropertyToNodeCollection(newNode.Nodes, objectType, propertyName);
                }
            }
            treeProperties.ExpandAll();
        }