2014-08-28 1 views
0

ComponentOne의 DataTree Grid를 사용하고 있습니다. 현재 DataTree 그리드에는 2 개의 레벨이 있습니다 (Parent & Child). 각 그리드의 각 행에는 사용자가 행을 선택할 수있는 체크 박스 열이 있습니다. 사용자가 부모 행을 선택하면 이벤트가 발생하고 flexgrid_CellChecked가 발생합니다. 자식 그리드가 선택되면, 발동 된 이벤트는 flexgrid_ChildCellChecked입니다. DataTree에 3 단계를 추가하고 가장 안쪽에있는 체크 상자가 선택되면 해당 이벤트가 발생하도록합니다. flexgrid_ChildChildCellChecked라고 부르 자.C#의 그리드에서 서로 다른 레벨의 다른 이벤트 핸들러 만들기

이 이벤트는 DataTree 클래스의 Expand (int 행) 메서드에서 인스턴스화됩니다. 문제는 첫 번째 자식 (레벨 2)이 확장되고 이벤트 ChildCellChecked 및 ChildChildCellChecked가 핸들러로 추가 될 수있는 경우입니다. 두 x 째 하위 (레벨 3)가 확장되면이 두 이벤트는 모두 널입니다. 내가 3 레벨 그리드의 두 번째 수준의 그리드 및 ChildChildCellChecked의 이벤트, ChildCellChecked를 만들 싶습니다

public class C1FlexDataTree : C1FlexGrid, ISupportInitialize 
{ 
    //-------------------------------------------------------------------------------- 
    #region ** fields 

    // reference to hidden column that contains details rows for each master record 
    // 
    // this is created automatically by a DataSet based on its Relations. 
    // 
    // e.g. if the parent table is 'Orders', this could be an 'OrderDetails' table 
    // with the order details for each order on the master data table. 
    // 
    private Column _colChild = null; 

    // child grid that displays the headers rows over the native header rows. 
    // 
    // this grid appears on top of all child controls and prevents children from 
    // hiding the parent grid's header rows when they scroll. 
    // 
    private GridHeader _hdr = null; // <<1.1>> 
// fire event to allow setting up child grids 
    // the event sender is the child grid that was just bound 
    public event EventHandler SetupColumns; 
    public event RowColEventHandler ChildCellChecked; 
    public event RowColEventHandler ChildChildCellChecked; 

    protected virtual void OnSetupColumns(object sender) 
    { 
     if (SetupColumns != null) 
      SetupColumns(sender, EventArgs.Empty); 
    } 

    protected virtual void OnChildCellChecked(object sender, RowColEventArgs e) 
    { 
     if (ChildCellChecked != null) 
     { 
      ChildCellChecked(sender, e); 
     } 
    } 

    protected virtual void OnChildChildCellChecked(object sender, RowColEventArgs e) 
    { 
     if (ChildChildCellChecked != null) 
     { 
      ChildChildCellChecked(sender, e); 
     } 
    } 
    // get top-level grid (overall parent) 
    public C1FlexDataTree ParentGrid 
    { 
     get 
     { 
      C1FlexDataTree parent = this; 
      while (parent.Parent is C1FlexDataTree) 
       parent = parent.Parent as C1FlexDataTree; 
      return parent; 
     } 
    } 
// expand row 
    public bool ExpandRow(int row) 
    { 
     // sanity 
     if (row < Rows.Fixed || row >= Rows.Count) 
     { 
      return false; 
     } 

     // check that the row is not already expanded 
     C1FlexDataTree childGrid = Rows[row].UserData as C1FlexDataTree; 
     if (childGrid != null) 
     { 
      return false; 
     } 

     // check that we have a data source for this row 
     object dataSource = _colChild != null? _colChild[row] : null; 
     if (!(dataSource is IBindingList)) 
     { 
      return false; 
     } 

     // ** fire before collapse event 
     var e = new RowColEventArgs(row, -1); 
     OnBeforeCollapse(e); 
     if (e.Cancel) 
     { 
      return false; 
     } 

     // add node row (unbound) to display child 
     Rows.InsertNode(row + 1, -1); 

     // make new row non-editable (it's just a placeholder) 
     Rows[row + 1].AllowEditing = false; 

     // create child grid 
     childGrid = new C1FlexDataTree(); 
     childGrid.Visible = false; 
     childGrid.ScrollBars = ScrollBars.Horizontal; 



      // hook up event handlers 
      //When there is only 2 levels this 'if' statement is not needed. 
      //But with 3 levels, the ChildCellChecked is null 
      if (ChildCellChecked != null) 
      { 
       childGrid.CellChecked += new RowColEventHandler(ChildCellChecked); 

     } 

     // attach child grid to parent, set data source 
     Controls.Add(childGrid); 
     childGrid.DataSource = dataSource; 

     // save references: 
     // child grid Tag property contains a reference to the parent row 
     // parent row UserData contains a reference to the child grid 
     childGrid.Tag = Rows[row]; 
     Rows[row].UserData = childGrid; 

     // make child grid visible, move it into position 
     childGrid.Visible = true; 
     childGrid.UpdatePosition(); 
     childGrid.Focus(); 
//When _colChild is null, the 3rd level is being expanded. 
//ChildChildCellChecked is null 
      if (childGrid._colChild == null) 
      {    
       childGrid.CellChecked += new RowColEventHandler(ChildChildCellChecked); 
      } 

      OnAfterCollapse(e); 

      // done 
      return true; 
     } 

:

은 확장 방법과 DataTree 클래스입니다.

그리드가 올바르게 표시되고 확장 및 축소 할 수 있습니다. 그러나 3 단계 그리드의 확인란을 클릭하면 이벤트가 실행되지 않습니다.

각 수준 그리드에 이벤트 처리기를 연결하려면 어떻게합니까?

UPDATE

수준이 2 인 경우, 확장되고있는 수준 식별하는 코드 조각 중 하나를 사용하여이 이벤트 ChildChildCellChecked은 null입니다.

첫 번째 레벨 호출 중에 Expand() 메소드가 호출되고 두 번째 레벨 호출 중에 디버그 모드에서 스크린 샷을 표시하는 문서를 첨부했습니다.

Expand()의 첫 번째 수준 호출 중에 ChildCellChecked가 만들어집니다.
두 번째 수준의 Expand() 호출 중에 ChildChildCellChecked가 null입니다. 예외가 발생합니다.

두 번째 수준에서 Expand()를 호출하는 동안 대리자 ChildChildCellChecked가 null 인 이유를 알 수 없습니다.

첨부 된 스크린 샷은 오류를 더 잘 나타낼 수 있습니다 ... 디버그 모드 중 2 번 촬영.

첫 번째 그립은 확장됩니다. 부모 모눈이 첫 번째 자식으로 확장 된 경우입니다. BOTH 이벤트가 정의 된 것을 볼 수 있습니다. ChildCellCheck 만 작성되었습니다. Delegate to ChildCellChecked event during first call Expand() Delegate to ChildChildCellChecked event during first call Expand()

두 번째 그리드가 확장되었습니다. Error showing exception during second call Expand() to assign ChildChildCellChecked delegate

사실 모두 위임()를 확장하는 제 통화 중 각 이벤트의 방법과 연관되어 첫번째 아이 그리드 제 2 레벨 그리드를 표시하도록 확장 될 때, 이는 에러이다. Expand() 두 번째 호출 중에 대리자가 모두 null입니다.

자식 그리드가 만들어 질 때 수준에 관계없이 그 자식 그리드에 이벤트 처리기가 만들어 질 것이라고 생각했습니다.두 번째 수준의 눈금에 두 번째 이벤트 처리기가 필요하지 않습니다. 확인란을 클릭하면 이벤트가 실행되고 이벤트 메서드 내에서 어떤 자식 그리드 수준에서 이벤트가 발생했는지 확인할 수 있습니다.

글로리아 내가 원래 게시물에 게시 한 것처럼

답변

0

here -

다음과 같은 의견을 참조하십시오 : 노드가 확장되면

  • 는, 아이 그리드 컨트롤에 추가됩니다 부모 컬렉션 마찬가지로 행을 축소하면 하위 모눈은 부모의 Controls 컬렉션에서 제거됩니다. 자식 눈금을 제거하는 동안 자식 HeaderGrid의 UserData가 지워집니다. 따라서 이벤트 처리기를 완전히 무효화합니다. 이것이 바로이 스 니펫이 직접 작동하지 않는 이유입니다.

  • 각 그리드에 이벤트를 추가하기 전에 모든 행을 확장하면 행당 하나의 자식 만있는 경우 완벽하게 작동합니다. 그러나 이것은 단지 하나의 어린이 행사가 제기 될 때 모든 어린이에게 어린이 행사가 요구되기 때문에 좀 더 일반적인 경우에는 효과가 없을 것입니다.

  • 구현을 시도 했으므로 최선의 시나리오는 틀림없이 DataTree 클래스의 ExpandRow 메서드에 자식 이벤트를 추가하는 것입니다. 이 방법은 행이 확장되거나 그리드가 생성 될 때마다 이벤트 핸들러가 그리드에 첨부됩니다. 현재 그리드가 '자식'또는 '자식 하위'의 이벤트와 연결되어야하는지 확인하기 위해 검사를 수행 할 수 있습니다. 다음 코드를 참조하십시오 : 당신의 조각에서

    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); 
    } 
    
  • 을 childGrid.Rows의 UserData를 [행] null의 경우 당신이 확인된다. 그러나 childGrid 행의 UserData는 항상 null입니다. 자식 모눈이 모눈에 추가 될 때마다 자식 모눈의 모든 행은 축소되거나 확장되지 않습니다.

  • 팁 : UserData를이 행에 대해 null의 경우,이 행이 축소되어 하나 또는 행이 어떤 childGrid 세 번째 점에서

    , 우리는 '차일'와 '차일을위한 이벤트를 만든이없는 의미 아이의 '. 이것은 부모 그리드에 대한 이벤트를 생성하지 않습니다. 따라서

    if (this.ParentGrid == this) 
    { 
         this.CellChecked+=new RowColEventHandler(Parent_CellChecked); 
    } 
    

중요 귀하의 DataTree 클래스의 생성자에 조각을 추가 할 수 있습니다 : 부모 그리드

모든 자식 그리드가 DataTree 될 것이다. 따라서 모든 자식 그리드의 행을 확장하면 ExpandRow 메서드가 트리거되어 결국 이벤트 처리기를 추가하려고합니다. ChildGrid의 ExpandRow 메서드가 부모 그리드와 같은 이벤트를 추가하지 않도록 올바른 조치를 취하십시오. 이것은 childGrid의 레벨을 검사하여 보장 할 수 있습니다. 그것은 단계에서 수행되는 3

+0

원래 질문에 대한 업데이트를 추가했습니다 ... –

0

DataTree 생성 할 때마다, (부모 개체의 자녀) 모두 포함 된 그리드가 동일한 이벤트를 구현하는 것이 있습니다. 그래서 같은 DataTree 클래스 이벤트 모두 ParentCheck, ChildCheckChildChildCheck을 만들 권리가 아니었다.우리가 DataTree 클래스 에게 ParentCheck, ChildCheckChildChildCheck 이벤트를 만들 때, 심지어 아이가 ChilChildCheck 이벤트를 실행하는 이유입니다. 이벤트를 CellChecked

DataTree 클래스에서 생성, 모든 그리드가 이벤트를 CellChecked 상속 관찰된다. 이것은 매우 유리한 상황이었습니다. 그리드의 계층 적 수준을 확인하기 만하면되었습니다.

확인란을 구현하는 것이 이벤트를 배치하는 데 가장 중요한 부분이었습니다. 체크 박스 부울 열 아무것도하지 그리 또는 포함컨트롤 (가 온라인 샘플의 일부에서 구현 될 때) 없기 때문에, 체크 박스는 따라서 이벤트와 개별적으로 연계 될 필요가 없습니다 CellChecked 이벤트는 기본 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 및 가 구현해야 ChildChildCellChecked.

부모 그리드에 액세스 할 수있는 경우 부모 그리드의 자식 하위에 액세스하는 등의 작업을 수행 할 수 있습니다. 이것은 아래 스 니펫에 묘사되어 있습니다. 하위 그리드는 상위 그리드가 생성 된 클래스에서 가져올 수 없습니다. 이 스 니펫을 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 
       } 
      } 
     } 
    } 
} 
+0

오류를 보여준 샘플 코드를 업데이트했습니다. 당신의 설명이 어떻게 작동하는지 보여주기 위해 내가 보낸 코드를 바꿀 수 있습니까? –

관련 문제