C# 已创建dCellChecked。 在Expand()的第二级调用期间,ChildCellChecked为null。这将导致一个异常
我不明白为什么在对Expand()的第二级调用期间,委托ChildCellChecked为null 附加的屏幕截图可以更好地显示错误。。。 在调试模式下拍摄2个屏幕截图 第一个网格被扩展。 此时父栅格将展开为第一个子栅格。 您可以看到这两个事件都已定义。仅创建了ChildCellCheck。 第二个网格被扩展。 展开第一个子网格以显示第二级网格时,出现以下错误: 实际上,在第一次调用Expand()期间,两个委托都与各自的事件方法相关联。在第二次调用Expand()期间,两个委托都为null 我原以为,当创建子网格时,不管级别如何,都会为该子网格创建一个事件处理程序。对于第二级网格,我不需要第二个事件处理程序。单击复选框时,将触发事件,并且在事件方法中,您可以确定触发事件的子网格级别C# 已创建dCellChecked。 在Expand()的第二级调用期间,ChildCellChecked为null。这将导致一个异常,c#,event-handling,c1flexgrid,C#,Event Handling,C1flexgrid,我不明白为什么在对Expand()的第二级调用期间,委托ChildCellChecked为null 附加的屏幕截图可以更好地显示错误。。。 在调试模式下拍摄2个屏幕截图 第一个网格被扩展。 此时父栅格将展开为第一个子栅格。 您可以看到这两个事件都已定义。仅创建了ChildCellCheck。 第二个网格被扩展。 展开第一个子网格以显示第二级网格时,出现以下错误: 实际上,在第一次调用Expand()期间,两个委托都与各自的事件方法相关联。在第二次调用Expand()期间,两个委托都为null
Gloria正如我在你原来的帖子上所说:- 请参阅以下评论:
- 展开节点时,会将子网格添加到父节点的控件集合中。类似地,折叠行时,子网格将从父网格的控件集合中删除。移除子网格时,将清除子网格的HeaderGrid的UserData。因此,它将使事件处理程序完全无效。这就是为什么这个片段不能直接工作的原因
- 如果在为每个网格添加事件之前展开所有行,那么在每行只有一个子项的情况下,它将非常有效。但是,这不适用于更一般的情况,因为只有一个孩子的事件发生时,所有孩子都会被称为“儿童事件”
- 正如您尝试实现的那样,最好的情况肯定是在DataTree类的ExpandRow方法中添加子事件。这样,无论何时展开行或创建网格,事件处理程序都会附加到网格。可以执行检查,查看当前网格是否应与“child”或“child的child”事件链接。请参阅以下代码段:
int level = 0; C1FlexDataTree parent = new C1FlexDataTree(); parent = childGrid; while (parent.Parent is C1FlexDataTree) { parent = parent.Parent as C1FlexDataTree; level++; } if (level == 1) { childGrid.CellChecked += new RowColEventHandler(child_CellChecked); } else if (level == 2) { childGrid.CellChecked += new RowColEventHandler(childchild_CellChecked); }
protected override void OnCellChecked(RowColEventArgs e) { base.OnCellChecked(e); // Access childs from a flex data tree if (this.Rows[e.Row].UserData != null) { C1FlexDataTree child = this.Rows[e.Row].UserData as C1FlexDataTree; foreach (Row childRow in child.Rows) { if (childRow.Index > 0) { childRow[1] = this.Rows[e.Row][1]; if (childRow.UserData != null) { C1FlexDataTree childchild = childRow.UserData as C1FlexDataTree; foreach (Row childchildRow in childchild.Rows) { if (childchildRow.Index > 0) childchildRow[1] = this.Rows[e.Row][1]; } } } } } // Check the level of grid C1FlexDataTree parent = this; int level = 0; while (parent.Parent is C1FlexDataTree) { level++; parent = parent.Parent as C1FlexDataTree; } if (level == 0) { MessageBox.Show("I am parent"); // Place your code for ParentCellChecked here } else if (level == 1) { MessageBox.Show("I am parent’s child"); // Place your code for ChildCellChecked here } else if (level == 2) { MessageBox.Show("I am parent’s child’s child"); // Place your code for ChildChildCellChecked here } }
- 在代码段中,您正在检查childGrid.Rows[row]的UserData是否为空。但是childGrid行的UserData总是空的。每当将子格线添加到格线时,子格线的每一行都会折叠或不可展开
- 提示:如果某行的UserData为null,则表示该行已折叠或该行没有任何子网格
在第三点中,我们为“childs”和“childs of childs”创建了事件。这不会为父网格创建事件。因此,您可能必须在DataTree类的构造函数中添加一个代码段
if (this.ParentGrid == this) { this.CellChecked+=new RowColEventHandler(Parent_CellChecked); }
父网格中的所有子网格都将是一个数据树。这就是为什么扩展每个子网格的行也会触发ExpandRow方法,并最终尝试添加事件处理程序。请采取正确的措施确保ChildGrid的ExpandRow方法不会添加类似父网格的事件。这可以通过检查childGrid的级别来确保。它在步骤3中执行。请注意,每次创建数据树时,所有嵌入式网格(父对象的子对象)都会实现相同的事件。因此,在同一个数据树类中创建ParentCheck、ChildCheck和ChildCheck事件是不对的。这就是为什么当我们在数据树类中创建ParentCheck、ChildCheck和ChildCheck事件时,即使是子级也会执行ChildCheck事件 当在数据树类中创建CellChecked事件时,可以观察到所有网格都继承了CellChecked事件。这是一个非常有利的情况,我们所要做的就是确定网格的层次结构 复选框的实现是放置事件的最重要部分。由于复选框只不过是一个布尔列,而不是字形或嵌入的控件(在一些联机示例中实现),因此复选框不需要与事件单独链接,因此,可以通过覆盖基本的CellChecked事件来实现CellChecked事件 请参阅以下代码段:
int level = 0;
C1FlexDataTree parent = new C1FlexDataTree();
parent = childGrid;
while (parent.Parent is C1FlexDataTree)
{
parent = parent.Parent as C1FlexDataTree;
level++;
}
if (level == 1)
{
childGrid.CellChecked += new RowColEventHandler(child_CellChecked);
}
else if (level == 2)
{
childGrid.CellChecked += new RowColEventHandler(childchild_CellChecked);
}
protected override void OnCellChecked(RowColEventArgs e)
{
base.OnCellChecked(e);
// Access childs from a flex data tree
if (this.Rows[e.Row].UserData != null)
{
C1FlexDataTree child = this.Rows[e.Row].UserData as C1FlexDataTree;
foreach (Row childRow in child.Rows)
{
if (childRow.Index > 0)
{
childRow[1] = this.Rows[e.Row][1];
if (childRow.UserData != null)
{
C1FlexDataTree childchild = childRow.UserData as C1FlexDataTree;
foreach (Row childchildRow in childchild.Rows)
{
if (childchildRow.Index > 0)
childchildRow[1] = this.Rows[e.Row][1];
}
}
}
}
}
// Check the level of grid
C1FlexDataTree parent = this;
int level = 0;
while (parent.Parent is C1FlexDataTree)
{
level++;
parent = parent.Parent as C1FlexDataTree;
}
if (level == 0)
{
MessageBox.Show("I am parent");
// Place your code for ParentCellChecked here
}
else if (level == 1)
{
MessageBox.Show("I am parent’s child");
// Place your code for ChildCellChecked here
}
else if (level == 2)
{
MessageBox.Show("I am parent’s child’s child");
// Place your code for ChildChildCellChecked here
}
}
请注意,在上面的代码段中,必须实现ParentCellChecked、ChildCellChecked和ChildCellChecked
也可以访问父网格的子网格的子网格…等等,如果我们可以访问父网格的话。下面的代码片段描述了这一点。请注意,子网格不能来自创建父网格的类。最好在DataTree类本身中使用此代码段
if (this.Rows[XthRow].UserData != null)
{
C1FlexDataTree child = this.Rows[e.Row].UserData as C1FlexDataTree;
foreach (Row childRow in child.Rows)
{
if (childRow.Index > 0)
{
// ALL THE CHILD’S ROW
if (childRow.UserData != null)
{
C1FlexDataTree childchild = childRow.UserData as C1FlexDataTree;
foreach (Row childchildRow in childchild.Rows)
{
if (childchildRow.Index > 0)
// ALL THE CHILD’S CHILD’S ROW
}
}
}
}
}
我更新了演示错误的示例代码。你能更改我发送的代码以显示你的解释是如何工作的吗?