我正在尝试构建一个datagridview,它将显示一些具有特定字段集的行,但也允许我显示一些“子行”,即可以在相关父行下面展开的行(如果是父行row有这些子节点 - datasoruce的一部分)唯一真正的问题是扩展的行将具有完全不同的字段(列)
这是否可以在Windows窗体中使用标准datagridview? 我假设我不得不在父网格的一行中的一个新的datagridview中进行鞋拔。
我们确实有Syncfusion套件,其中包括gridgroupingcontrol。但经过多次拔毛和其他疼痛。我完全放弃了。
答案 0 :(得分:3)
是的,这可以做到。
使用外键 - 父键列在数据集设计器或两个表之间的代码中设置数据关系。
如果在数据集设计器中,请将嵌套属性设置为true。然后,这将为您提供datagrid视图中每个父行下的子记录。
答案 1 :(得分:0)
简答:不。你需要一个自定义组件。
在制作分层树视图方面有很多很好的努力。与CodeProject文章中的TreeView with Columns或FlexGrid一样(付费)。我知道你想要子节点上的不同字段,我不确定这些控件在多大程度上支持它。我知道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);
}
}