Win Forms DataGridView - 显示分层父/子行

时间:2011-03-22 10:56:58

标签: c# .net datagridview expand

我正在尝试构建一个datagridview,它将显示一些具有特定字段集的行,但也允许我显示一些“子行”,即可以在相关父行下面展开的行(如果是父行row有这些子节点 - datasoruce的一部分)唯一真正的问题是扩展的行将具有完全不同的字段(列)

这是否可以在Windows窗体中使用标准datagridview? 我假设我不得不在父网格的一行中的一个新的datagridview中进行鞋拔。

我们确实有Syncfusion套件,其中包括gridgroupingcontrol。但经过多次拔毛和其他疼痛。我完全放弃了。

3 个答案:

答案 0 :(得分:3)

是的,这可以做到。

使用外键 - 父键列在数据集设计器或两个表之间的代码中设置数据关系。

如果在数据集设计器中,请将嵌套属性设置为true。然后,这将为您提供datagrid视图中每个父行下的子记录。

答案 1 :(得分:0)

简答:不。你需要一个自定义组件。

在制作分层树视图方面有很多很好的努力。与CodeProject文章中的TreeView with ColumnsFlexGrid一样(付费)。我知道你想要子节点上的不同字段,我不确定这些控件在多大程度上支持它。我知道FlexGrid支持对不同行的列进行一些自定义,但它可能涉及一些手动工作 - 数据绑定不受支持。

最后,您可能想要考虑一下您对自定义GridView的想法是否是解决问题的最佳方法。 Master-Detail-view能否成为更好的方法?

PS:我不隶属于ComponentOne,但我在项目中使用了FlexGrid。

答案 2 :(得分:0)

 public class QuestionNode
    {
        public decimal QuestionCode { get; set; }
        public decimal parentQuestionCode { get; set; }        
        public string AssessmentSection { get; set; }
        public string shortName { get; set; }
        public List<QuestionNode> ChildQuestionNode { get; set; }
    }

            CellStyle cs = grdData.Styles.Normal;
            cs.Border.Direction = BorderDirEnum.Vertical;
            cs.TextAlign = TextAlignEnum.LeftCenter;
            cs.WordWrap = false;
            cs = grdData.Styles.Add("Data");
            cs.BackColor = SystemColors.Info;
            cs.ForeColor = SystemColors.InfoText;
            cs = grdData.Styles.Add("SourceNode");
            cs.BackColor = Color.Yellow;
            cs.Font = new Font(grdData.Font, FontStyle.Bold);

            // outline tree
            grdData.Tree.Column = 0;
            grdData.Tree.Style = TreeStyleFlags.Simple;
            grdData.AllowMerging = AllowMergingEnum.Nodes;

            // other
            grdData.AllowResizing = AllowResizingEnum.Columns;
            grdData.SelectionMode = SelectionModeEnum.Cell;



            grdData.SuspendLayout();
            grdData.Rows.Fixed = 1;
            //grdData.DataSource = dt;
            grdData.Cols[0].Visible = false;
            grdData.Cols[1].Visible = false;
            if (_ID == 9)
                grdData[0, 0] = "HCFA-672 Assessment";
            else if (_ID == 10)
                grdData[0, 0] = "HCFA-802 Assessment";

            RcsResidentReporterBL resReportBL = new RcsResidentReporterBL();
            DataTable dt = resReportBL.GetCriteriaQueslkp(_ID, facilityID);

            List<QuestionNode> qtree = new List<QuestionNode>();

            foreach (DataRow dr in dt.Rows)
            {
                QuestionNode parentNode = new QuestionNode();
                parentNode.QuestionCode = Convert.ToDecimal(dr["QuestionCode"]);
                parentNode.AssessmentSection = dr["AssessmentSection"].ToString();
                parentNode.parentQuestionCode =       Convert.ToDecimal(dr["ParentQuestionCode"]);
                parentNode.shortName = dr["ShortName"].ToString();
                var qry = dt.AsEnumerable().Where(x => x.Field<int>("ParentQuestionCode") == parentNode.QuestionCode)
                                            .Select(x => new { QuestionCode = x.Field<int>("QuestionCode"), AssessmentSection = x.Field<string>("AssessmentSection"), ShortName = x.Field<string>("ShortName") }).ToList();
                parentNode.ChildQuestionNode = new List<QuestionNode>();
                parentNode.ChildQuestionNode.Add(parentNode);
                qtree.Add(parentNode);
            }

                Action<QuestionNode> SetChildren = null;
                SetChildren = parent =>
                {
                    parent.ChildQuestionNode = qtree
                        .Where(childItem => childItem.parentQuestionCode == parent.QuestionCode)
                        .ToList();

                    //Recursively call the SetChildren method for each child.
                    parent.ChildQuestionNode
                        .ForEach(SetChildren);
                };

                //Initialize the hierarchical list to root level items
                List<QuestionNode> hierarchicalItems = qtree
                    .Where(rootItem => rootItem.parentQuestionCode == 0)
                    .ToList();

                //Call the SetChildren method to set the children on each root level item.
                hierarchicalItems.ForEach(SetChildren);

                foreach (QuestionNode qst in hierarchicalItems)
                {
                    GetChildren(qst, 0, true, -1);
                }



 private void GetChildren(QuestionNode parentNode, int level, bool useC1Way, int parentrow)
        {

            // add new row for this node
            int row;
            if (useC1Way == true)
            {
                //This is the code by C1
                // add new row for this node
                row = grdData.Rows.Count;
                grdData.Rows.Add();
                grdData[row, 0] = parentNode.AssessmentSection;
                if (parentNode.ChildQuestionNode == null)
                {
                    grdData[row, 1] = "?";
                    grdData.SetCellStyle(row, 1, grdData.Styles["Data"]);
                }

                // make new row a node
                grdData.Rows[row].IsNode = true;
                grdData.Rows[row].Node.Level = level;
            }
            else
            {
                //And this is my different version: at level 0, add a row. At child levels, insert "last child"
                if (level == 0)
                {

                    Row zeile = this.grdData.Rows.Add();
                    zeile.IsNode = true;
                    zeile.Node.Level = 0;

                    grdData[zeile.Index, 0] = parentNode.AssessmentSection;

                    //This also works...
                    //Node nodeGrid = grdData.Rows.AddNode(0);
                    //grdData[nodeGrid.Row.Index, 0] = node.Name;
                }
                else
                {
                    //int row = grdData.Rows.Count;
                    //grdData.Rows.Add();
                    grdData.Rows[parentrow].Node.AddNode(NodeTypeEnum.LastChild, parentNode.AssessmentSection);

                }
                row = grdData.Rows.Count - 1;
            }
            //grdData[row, 0] = node.Name;
            if (parentNode.ChildQuestionNode == null)
            {
                grdData[row, 1] ="?";
                grdData.SetCellStyle(row, 1, grdData.Styles["Data"]);
            }

            // make new row a node
            //grdData.Rows[row].IsNode = true;
            //grdData.Rows[row].Node.Level = level;

            // if this node has children, get them as well
            if (parentNode.ChildQuestionNode != null  && parentNode.ChildQuestionNode.Count > 1)
            {
                // recurse to get children
                foreach (QuestionNode child in parentNode.ChildQuestionNode)
                    GetChildren(child, level + 1, useC1Way, row);
            }
        }