DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

TreeViewのノードのテキストをユーザーが編集できるようにする

エクスプローラでフォルダ名を変更する時、そのフォルダをゆっくり2回クリックするか、F2キーを押すことにより、新しいフォルダ名を入力できるようになります。ここではこれと同じことがTreeViewコントロールでできるようにする方法を紹介します。

基本的には、「ListViewのアイテムのテキストをユーザーが編集できるようにする」で紹介している方法と同じです。主な説明はそちらで行い、ここでは簡単な説明と、サンプルを示します。

ゆっくり2回クリックすることで編集できるようにするには、TreeViewコントロールのLabelEditプロパティをTrueにします。また、F2キーを押すことで編集できるようにするには、TreeViewのKeyUpイベントハンドラでF2キーが押されたかを調べ、押されていればTreeNode.BeginEditメソッドによりアイテムのラベルの編集を開始します。

ラベルの編集が始まる前にBeforeLabelEditイベントが、編集が終わった時にAfterLabelEditイベントが発生します。それぞれのイベントハンドラでNodeLabelEditEventArgs.CancelEditプロパティをTrueにすることにより、編集をキャンセルすることができます。

次の例では、ツリービューコントロール"TreeView1"のツリーノードをユーザーが編集できるようにしています。BeforeLabelEditイベントハンドラで、ルートのノードを編集できないようにしています。また、AfterLabelEditイベントハンドラで、同じ親ノード内の同じ階層に同じラベルのノードがあるかを調べ、もしあればキャンセルしています。

VB.NET
コードを隠すコードを選択
'フォームのLoadイベントハンドラ
Private Sub Form1_Load(ByVal sender As Object, _
                       ByVal e As EventArgs) Handles MyBase.Load
    'ツリーノードをユーザーが編集できるようにする
    TreeView1.LabelEdit = True

    'イベントハンドラの追加
    AddHandler TreeView1.BeforeLabelEdit, AddressOf TreeView1_BeforeLabelEdit
    AddHandler TreeView1.AfterLabelEdit, AddressOf TreeView1_AfterLabelEdit
    AddHandler TreeView1.KeyUp, AddressOf TreeView1_KeyUp
End Sub

'BeforeLabelEditイベントハンドラ
'ツリーノードのラベルの編集が開始された時
Private Sub TreeView1_BeforeLabelEdit(ByVal sender As Object, _
                                      ByVal e As NodeLabelEditEventArgs)
    'ルートのコードは編集できないようにする
    If e.Node.Parent Is Nothing Then
        e.CancelEdit = True
    End If
End Sub

'AfterLabelEditイベントハンドラ
'ツリーノードのラベルの編集された時
Private Sub TreeView1_AfterLabelEdit(ByVal sender As Object, _
                                     ByVal e As NodeLabelEditEventArgs)
    'ラベルが変更されたか調べる
    'e.LabelがNothingならば、変更されていない
    If Not (e.Label Is Nothing) Then
        '同名のノードが同じ親ノード内にあるか調べる
        If Not (e.Node.Parent Is Nothing) Then
            For Each n As TreeNode In e.Node.Parent.Nodes
                '同名のノードがあるときは編集をキャンセルする
                If Not (n Is e.Node) AndAlso n.Text = e.Label Then
                    MessageBox.Show("同名のノードがすでにあります。")
                    '編集をキャンセルして元に戻す
                    e.CancelEdit = True
                    Return
                End If
            Next
        End If
    End If
End Sub

'KeyUpイベントハンドラ
'TreeView1でキーが離れた時
Private Sub TreeView1_KeyUp(ByVal sender As Object, _
                            ByVal e As KeyEventArgs)
    Dim tv As TreeView = DirectCast(sender, TreeView)
    'F2キーが離されたときは、フォーカスのあるアイテムの編集を開始
    If e.KeyCode = Keys.F2 AndAlso _
        Not (tv.SelectedNode Is Nothing) AndAlso _
        tv.SelectedNode.IsEditing Then

        tv.SelectedNode.BeginEdit()
    End If
End Sub
C#
コードを隠すコードを選択
//フォームのLoadイベントハンドラ
private void Form1_Load(object sender, EventArgs e)
{
    //ツリーノードをユーザーが編集できるようにする
    TreeView1.LabelEdit = true;

    //イベントハンドラの追加
    TreeView1.BeforeLabelEdit += new NodeLabelEditEventHandler(TreeView1_BeforeLabelEdit);
    TreeView1.AfterLabelEdit += new NodeLabelEditEventHandler(TreeView1_AfterLabelEdit);
    TreeView1.KeyUp += new KeyEventHandler(TreeView1_KeyUp);
}

//BeforeLabelEditイベントハンドラ
//ツリーノードのラベルの編集が開始された時
private void TreeView1_BeforeLabelEdit(object sender, NodeLabelEditEventArgs e)
{
    //ルートのコードは編集できないようにする
    if (e.Node.Parent == null)
    {
        e.CancelEdit = true;
    }
}

//AfterLabelEditイベントハンドラ
//ツリーノードのラベルの編集された時
private void TreeView1_AfterLabelEdit(object sender, NodeLabelEditEventArgs e)
{
    //ラベルが変更されたか調べる
    //e.Labelがnullならば、変更されていない
    if (e.Label != null)
    {
        //同名のノードが同じ親ノード内にあるか調べる
        if (e.Node.Parent != null)
        {
            foreach (TreeNode n in e.Node.Parent.Nodes)
            {
                //同名のノードがあるときは編集をキャンセルする
                if (n != e.Node && n.Text == e.Label)
                {
                    MessageBox.Show("同名のノードがすでにあります。");
                    //編集をキャンセルして元に戻す
                    e.CancelEdit = true;
                    return;
                }
            }
        }
    }
}

//KeyUpイベントハンドラ
//TreeView1でキーが離れた時
private void TreeView1_KeyUp(object sender, KeyEventArgs e)
{
    TreeView tv = (TreeView)sender;
    //F2キーが離されたときは、フォーカスのあるアイテムの編集を開始
    if (e.KeyCode == Keys.F2 && tv.SelectedNode != null && tv.LabelEdit)
    {
        tv.SelectedNode.BeginEdit();
    }
}

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • イベントハンドラの意味が分からない、C#のコードをそのまま書いても動かないという方は、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。