FlexGrid for WinForms
ノードの操作
ツリーグリッド > ノードの操作

ツリーグリッドでは、データを構造化された形式で表示できるだけでなく、ノードに対してさまざまな操作を実行できます。Node クラスで提供されているさまざまなメソッドを使用して、ノードを追加、削除、移動、取得できます。

ノードの操作

ノードの追加

Node クラスの AddNode メソッドを使用して、ツリーグリッド内の特定の位置にノードを追加できます。これにより、新しいノード行がコレクションに追加されます。このメソッドは、引数として NodeTypeEnum 列挙を受け取ります。これを使用して、別の特定のノードとの関係を指定してノードを追加できます。

次のコードは、WinForms ツリーグリッドの特定の位置にノードを追加する方法を示しています。

private void cmbAdd_SelectionChangeCommitted(object sender, System.EventArgs e)
{
   // 現在の行ノードを取得します
   Node nd = flex.Rows[flex.Row].Node;
   // ユーザーの要求に応じて相対を追加します
   // (could be a child or a sibling)
   nd.AddNode((NodeTypeEnum)(cmbAdd.SelectedIndex + 2), cmbAdd.Text);
   flex.Focus();
}     
Private Sub cmbAdd_SelectionChangeCommitted(ByVal sender As Object, ByVal e As EventArgs)
    ' 現在の行ノードを取得します
    Dim nd As Node = flex.Rows(flex.Row).Node
    ' ユーザーの要求に応じて相対を追加します
    ' (could be a child or a sibling)
    nd.AddNode(CType(cmbAdd.SelectedIndex + 2, NodeTypeEnum), cmbAdd.Text)
    flex.Focus()
End Sub 

ノードの削除

Node クラスの RemoveNode メソッドを使用して、選択したノードをツリーグリッドから削除できます。

次のコード例は、WinForms ツリーグリッドからノードを削除する方法を示しています。

private void btnDelete_Click(object sender, System.EventArgs e)
{
  // 現在のノードを取得します
  Node nd = null;
  if ( flex.Rows.Count > 0 && flex.Row >= 0 && flex.Row < flex.Rows.Count)
  {
    nd = flex.Rows[flex.Row].Node;
  }
  if (nd != null)
  {
     // FlexGridからノードを削除します
     nd.RemoveNode();
     flex.Focus();
  }
}     
Private Sub btnDelete_Click(ByVal sender As Object, ByVal e As EventArgs)
    ' 現在のノードを取得します
    Dim nd As Node = Nothing
    If flex.Rows.Count > 0 AndAlso flex.Row >= 0 AndAlso flex.Row < flex.Rows.Count Then
        nd = flex.Rows(flex.Row).Node
    End If
    If nd IsNot Nothing Then
        ' FlexGridからノードを削除します
        nd.RemoveNode()
        flex.Focus()
    End If
End Sub

ノードの移動

ツリーグリッドでは、Node クラスの Move メソッドを使用して、ノード行を別の位置に移動できます。このメソッドは、引数として NodeMoveEnum 列挙を受け取ります。これを使用して、ノードを移動する方向を指定できます。

次のコードを使用すると、WinForms ツリーグリッドのノードを別の位置に移動できます。

private void btnMove_Click(object sender, System.EventArgs e)
{
   // 現在の行のノードを取得します
   Node nd = flex.Rows[flex.Row].Node;
   // ユーザーが選択した動きを適用します
   // (これにより、選択したノードが移動します)
   if (sender == btnMoveOut) nd.Move(NodeMoveEnum.Out);
   else if (sender == btnMoveIn) nd.Move(NodeMoveEnum.In);
   else if (sender == btnMoveUp) nd.Move(NodeMoveEnum.Up);
   else if (sender == btnMoveDown) nd.Move(NodeMoveEnum.Down);
   else if (sender == btnMoveFirst) nd.Move(NodeMoveEnum.First);
   else if (sender == btnMoveLast) nd.Move(NodeMoveEnum.Last);
   // ノードがまだ表示されていることを確認します
   nd.EnsureVisible();
   flex.Focus();
}  
Private Sub btnMove_Click(ByVal sender As Object, ByVal e As EventArgs)
    ' 現在の行のノードを取得します
    Dim nd As Node = flex.Rows(flex.Row).Node
    ' ユーザーが選択した動きを適用します
    ' (これにより、選択したノードが移動します)   
    If sender Is btnMoveOut Then
        nd.Move(NodeMoveEnum.Out)
    ElseIf sender Is btnMoveIn Then
        nd.Move(NodeMoveEnum.[In])
    ElseIf sender Is btnMoveUp Then
        nd.Move(NodeMoveEnum.Up)
    ElseIf sender Is btnMoveDown Then
        nd.Move(NodeMoveEnum.Down)
    ElseIf sender Is btnMoveFirst Then
        nd.Move(NodeMoveEnum.First)
    ElseIf sender Is btnMoveLast Then
        nd.Move(NodeMoveEnum.Last)
    End If
    ' ノードがまだ表示されていることを確認します
    nd.EnsureVisible()
    flex.Focus()
End Sub 

ノードの選択

ツリーグリッドでは、Node クラスの GetNode メソッドを使用することで、さまざまな操作を実行する対象のノードを選択できます。このメソッドは、NodeTypeEnum 列挙をパラメータとして受け取ります。これを使用して、別の特定のノードとの関係を指定してノードを選択できます。

次のコードは、WinForms ツリーグリッドの特定のノードを取得し、それを選択状態で表示する方法を示しています。

private void cmbSelect_SelectionChangeCommitted(object sender, System.EventArgs e)
{
   // 現在の行のノードを取得します
   Node nd = flex.Rows[flex.Row].Node;
   // ユーザーが選択したノードを取得します
   nd = nd.GetNode((NodeTypeEnum)cmbSelect.SelectedIndex);
   // 失敗した場合は、メッセージを表示します
   if (nd == null)
   {
      MessageBox.Show("Can't find " + cmbSelect.Text + " for this node.");
      return;
    }
    // ノードを選択し、それが表示されていることを確認します(スクロールして表示します)
    nd.Select();
    nd.EnsureVisible();
    flex.Focus();
}      
Private Sub cmbSelect_SelectionChangeCommitted(ByVal sender As Object, ByVal e As EventArgs)
    ' 現在の行のノードを取得します
    Dim nd As Node = flex.Rows(flex.Row).Node
    ' ユーザーが選択したノードを取得します
    nd = nd.GetNode(CType(cmbSelect.SelectedIndex, NodeTypeEnum))
    ' 失敗した場合は、メッセージを表示します
    If nd Is Nothing Then
        MessageBox.Show("Can't find " & cmbSelect.Text & " for this node.")
        Return
    End If
    ' ノードを選択し、それが表示されていることを確認します(スクロールして表示します)
    nd.[Select]()
    nd.EnsureVisible()
    flex.Focus()
End Sub

ノードの展開と折りたたみ

下のコードに示すように、Node クラスの Collapsed プロパティを使用すると、ツリーグリッドアプリケーション内のすべてのノードを展開/折りたたむことができます。この機能は、ノードヘッダー間をグループとして移動する必要がある場合に便利です。

次のコードは、WinForms ツリーグリッドでノードを展開/折りたたむ方法を示しています。

foreach (Row row in flex.Rows.Cast<Row>().Where(rw => rw.IsNode == true))
{
        Node node = row.Node;
        node.Collapsed = false;
}

foreach (Row row in flex.Rows.Cast<Row>().Where(rw => rw.IsNode == true))
{
        Node node = row.Node;
        node.Collapsed = true;
}                
    For Each row As Row In flex.Rows.Cast(Of Row)().Where(Function(rw) rw.IsNode = True)
        Dim node As Node = row.Node
        node.Collapsed = False
    Next

    For Each row As Row In flex.Rows.Cast(Of Row)().Where(Function(rw) rw.IsNode = True)
        Dim node As Node = row.Node
        node.Collapsed = True
    Next       

ノードのドラッグアンドドロップ

ツリーグリッドでは、MouseUpMouseDownMouseMove の各イベントを処理することで、選択したノードを特定の位置にドラッグアンドドロップすることができます。

次のコードは、WinForms ツリーグリッドのノードをユーザーがドラッグアンドドロップできるようにします。 

private void flex_MouseDown(object sender, MouseEventArgs e)
{
   m_DragInfo.checkDrag = false;
   // 左ボタンを押すと、移動しません。 ドラッグするマウスの追跡を開始します
   if (e.Button != MouseButtons.Left) return;
   if (!chkDrag.Checked || m_DragInfo.dragging) return;
   if (flex.MouseRow < flex.Rows.Fixed || flex.MouseCol != 0) return;
   // 現在の行とマウスの位置を保存します
   m_DragInfo.row = flex.Row;
   m_DragInfo.mouseDown = new Point(e.X, e.Y);
   // チェックを開始します
   m_DragInfo.checkDrag = true;
}
private void flex_MouseMove(object sender, MouseEventArgs e)
{
   // チェックしてユーザーが許容範囲を超えた場合は、ドラッグを開始します
   if (!m_DragInfo.checkDrag || e.Button != MouseButtons.Left) return;
   if (Math.Abs(e.X - m_DragInfo.mouseDown.X) +
   Math.Abs(e.Y - m_DragInfo.mouseDown.Y) <= DRAGTOL) return;
   // フラグを更新します
   m_DragInfo.dragging = true;
   // Sets cursor and highlight node
   CellStyle cs = flex.Styles["SourceNode"];
   flex.Cursor = Cursors.NoMove2D;
   flex.SetCellStyle(m_DragInfo.row, 0, cs);
   // ここにドロップできるかどうかを確認します
   Cursor c = (NoDropHere()) ? Cursors.No : Cursors.NoMove2D;
   if (c != flex.Cursor) flex.Cursor = c;
}
    
private bool NoDropHere()
{
   // カーソルの下の行は無効です
   if (flex.MouseRow < flex.Rows.Fixed) return true;
   // カーソルの下の列が無効です
   if (flex.MouseCol < flex.Cols.Fixed) return true;
   if (flex.GetDataDisplay(flex.Row, 0) == "SKU") return true;
   return false;
}
     
private void flex_MouseUp(object sender, MouseEventArgs e)
{
   // マウスが再び下がるまでチェックしないでください
   m_DragInfo.checkDrag = false;
   // Not dragging? we're done
   if (!m_DragInfo.dragging) return;
   // ドラッグを停止します
   m_DragInfo.dragging = false;
   flex.SetCellStyle(m_DragInfo.row, 0, (CellStyle)null);
   flex.Cursor = Cursors.Default;
   // ドロップが許可されているかどうかをテストします
   if (NoDropHere()) return;
   // ノードを新しい親ノードに移動します
   Node ndSrc = flex.Rows[m_DragInfo.row].Node;
   Node ndDst = flex.Rows[flex.Row].Node;
   ndSrc.Move(NodeMoveEnum.ChildOf, ndDst);
   ndSrc.Select();
}
internal struct DRAGINFO
{
  public bool dragging;   // 現在ドラッグ中
  public bool checkDrag;  // 現在、マウスをチェックしてドラッグを開始しています
  public int row;     // ドラッグされている行のインデックス
  public Point mouseDown; //マウスダウンの位置
}           
Private Sub flex_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs)
        m_DragInfo.checkDrag = False
        ' 左ボタンを押すと、移動しません。 ドラッグするマウスの追跡を開始します
        If e.Button IsNot MouseButtons.Left Then Return
        If Not chkDrag.Checked OrElse m_DragInfo.dragging Then Return
        If flex.MouseRow < flex.Rows.Fixed OrElse flex.MouseCol <> 0 Then Return
        ' 現在の行とマウスの位置を保存します
        m_DragInfo.row = flex.Row
        m_DragInfo.mouseDown = New Point(e.X, e.Y)
        ' チェックを開始します
        m_DragInfo.checkDrag = True
    End Sub
    Private Sub flex_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs)
        ' チェックしてユーザーが許容範囲を超えた場合は、ドラッグを開始します
        If Not m_DragInfo.checkDrag OrElse e.Button IsNot MouseButtons.Left Then Return
        If Math.Abs(e.X - m_DragInfo.mouseDown.X) + Math.Abs(e.Y - m_DragInfo.mouseDown.Y) <= DRAGTOL Then Return
        ' フラグを更新します
        m_DragInfo.dragging = True
        ' カーソルを設定し、ノードを強調表示します
        Dim cs As CellStyle = flex.Styles("SourceNode")
        flex.Cursor = Cursors.NoMove2D
        flex.SetCellStyle(m_DragInfo.row, 0, cs)
        ' ここにドロップできるかどうかを確認します
        Dim c As Cursor = If((NoDropHere()), Cursors.No, Cursors.NoMove2D)
        If c IsNot flex.Cursor Then flex.Cursor = c
    End Sub
    Private Function NoDropHere() As Boolean
        ' カーソルの下の行は無効です
        If flex.MouseRow < flex.Rows.Fixed Then Return True
        ' カーソルの下の列が無効です
        If flex.MouseCol < flex.Cols.Fixed Then Return True
        If flex.GetDataDisplay(flex.Row, 0) Is "SKU" Then Return True
        Return False
    End Function
    Private Sub flex_MouseUp(ByVal sender As Object, ByVal e As MouseEventArgs)
        ' マウスが再び下がるまでチェックしないでください
        m_DragInfo.checkDrag = False
        If Not m_DragInfo.dragging Then Return
        ' ドラッグを停止します
        m_DragInfo.dragging = False
        flex.SetCellStyle(m_DragInfo.row, 0, CType(Nothing, CellStyle))
        flex.Cursor = Cursors.[Default]
        ' ドロップが許可されているかどうかをテストします
        If NoDropHere() Then Return
        ' ノードを新しい親ノードに移動します
        Dim ndSrc As Node = flex.Rows(m_DragInfo.row).Node
        Dim ndDst As Node = flex.Rows(flex.Row).Node
        ndSrc.Move(NodeMoveEnum.ChildOf, ndDst)
        ndSrc.[Select]()
    End Sub
    Friend Structure DRAGINFO
        Public dragging As Boolean   ' 現在ドラッグ中
        Public checkDrag As Boolean  ' 現在、マウスをチェックしてドラッグを開始しています
        Public row As Integer     ' ドラッグされている行のインデックス
        Public mouseDown As Point ' マウスダウンの位置
    End Structure