Steps to reproduce: 1. expand a parent row 2. remove the first child row (e.g. 'Jon Smith') by selecting the child row and press the button at the top 3. remove the second (last) child row (in this case 'Pete van Dijk') the same way Here is the code snippet: public partial class Form1 : Form { private List<Department> _departments; public Form1() { InitializeComponent(); SetGridParentColumns(); SetGridChildTemplate(); InitData(); grid.RowSourceNeeded += grid_RowSourceNeeded; } private void InitData() { _departments = new List<Department>(2); Department dep1 = new Department() { DepartmentId = 1, Name = "Accounting" }; Department dep2 = new Department() { DepartmentId = 2, Name = "Finance" }; Employee emp1 = new Employee() { DepartmentId = 1, EmployeeId = 1, FirsName = "John", LastName = "Smith" }; Employee emp2 = new Employee() { DepartmentId = 1, EmployeeId = 2, FirsName = "Pete", LastName = "van Dijk" }; Employee emp3 = new Employee() { DepartmentId = 2, EmployeeId = 3, FirsName = "Mark", LastName = "Smith" }; Employee emp4 = new Employee() { DepartmentId = 2, EmployeeId = 4, FirsName = "Jan", LastName = "Janssen" }; dep1.Employees = new List<Employee>() { emp1, emp2 }; dep2.Employees = new List<Employee>() { emp3, emp4 }; _departments.Add(dep1); _departments.Add(dep2); grid.DataSource = _departments; grid.AllowAddNewRow = false; grid.BestFitColumns(); } private void SetGridParentColumns() { grid.AutoGenerateColumns = false; grid.Columns.Add("DepartmentId", "DepartmentId", "DepartmentId"); grid.Columns.Add("Name", "Name", "Name"); } private void SetGridChildTemplate() { grid.Templates.Clear(); GridViewTemplate childTemplate = new GridViewTemplate(); childTemplate.Columns.Add("EmployeeId"); childTemplate.Columns.Add("DepartmentId"); childTemplate.Columns.Add("FirstName"); childTemplate.Columns.Add("LastName"); grid.Templates.Add(childTemplate); childTemplate.HierarchyDataProvider = new GridViewEventDataProvider(childTemplate); } private void grid_RowSourceNeeded(object sender, GridViewRowSourceNeededEventArgs e) { Department dep = e.ParentRow.DataBoundItem as Department; foreach (Employee employee in dep.Employees) { GridViewRowInfo gridRow = e.Template.Rows.NewRow(); gridRow.Cells["EmployeeId"].Value = employee.EmployeeId; gridRow.Cells["DepartmentId"].Value = employee.DepartmentId; gridRow.Cells["FirstName"].Value = employee.FirsName; gridRow.Cells["LastName"].Value = employee.LastName; e.SourceCollection.Add(gridRow); } e.Template.AllowAddNewRow = false; e.Template.BestFitColumns(); } private void btnRemoveChildRow_Click(object sender, EventArgs e) { GridViewRowInfo row = grid.SelectedRows[0]; if (row.ViewTemplate.Parent == null) return; //department (parent) row, so don't remove it int employeeId = Convert.ToInt32(row.Cells["EmployeeId"].Value); int departmentId = Convert.ToInt32(row.Cells["DepartmentId"].Value); Department dep = GetDepartment(departmentId); dep.RemoveEmployee(employeeId); row.ViewTemplate.Refresh(); } private Department GetDepartment(int departmentId) { foreach (Department dep in _departments) if (dep.DepartmentId == departmentId) return dep; return null; } } public class Department { public int DepartmentId { get; set; } public string Name { get; set; } public List<Employee> Employees { get; set; } public void RemoveEmployee(int employeeId) { Employee empToRemove = null; foreach (Employee emp in Employees) { if (emp.EmployeeId == employeeId) { empToRemove = emp; break; } } if (empToRemove != null) Employees.Remove(empToRemove); } } public class Employee { public int DepartmentId { get; set; } public int EmployeeId { get; set; } public string FirsName { get; set; } public string LastName { get; set; } } Workaround: use the ViewInfo.Refresh method instead of the ViewTemplate.Refresh method