TreeView for WinForms
カスタムノード

TreeView では、デフォルトのノードの代わりにカスタムノードを作成して表示することができます。カスタムプロパティを追加したり、さまざまなカスタマイズを表示することができます(画像の挿入/拡大縮小/配置、境界線の表示、フォントのスタイルと色のカスタマイズ、サイズの変更など)。TreeView でカスタムノードを設定するには、C1TreeColumnCustomContentPresenter プロパティを設定します。

Note: The SetStyle method of the CustomContentPresenter class supports gradients while using custom nodes in C1TreeView control with C1.Win.C1Themes.

次の図に、TreeView のカスタムノードを示します。

TreeView でカスタムノードを作成するには、デフォルトノードをオーバーライドしてカスタムノードに適用されるプロパティとメソッドを定義したカスタムクラスを作成します。カスタムクラスを作成したら、そのインスタンスを初期化し、CustomContentPresenter プロパティを使用してカスタムノードを設定します。

次のコードスニペットは、カスタムクラスを作成し、カスタムノードの主な要素を定義する方法を示します。

               
Public Class CategoryCustomNode
    Inherits CustomContentPresenter
    ' レベル 0
    Private _name As TextElement
    Private _description As TextElement
    Private _img As ImageElement
    Private _rw As RowPanel
    ' レベル 1
    Private _product As TextElement

    Public Sub New()
        ' レベル 0
        ' initテキスト要素
        ' name
        _name = New TextElement()
        _name.Style = New Style()
        ' 説明
        _description = New TextElement()
        _description.Style = New Style()
        _description.Width = 120
        ' イメージ要素をを初期化します
        _img = New ImageElement()
        _img.Style = New Style()
        _img.Size = New Size(70, 50)
        ' テキスト要素のグリッドを初期化します
        Dim cp = New ColumnPanel()
        cp.Children.Add(_name)
        cp.Children.Add(_description)
        ' イメージのためにパネルを初期化します
        _rw = New RowPanel()
        _rw.Children.Add(cp)
        _rw.Children.Add(_img)
        _rw.Style = New Style()
        _rw.Style.VerticalAlignment = Alignment.Center
        ' レベル 1
        _product = New TextElement()
        _product.Style = New Style()
    End Sub

    Public Overrides ReadOnly Property ToolTipText() As String
        Get
            Return _name.Text
        End Get
    End Property

    Public Overrides Sub SetStyle(styles As TreeNodeCellStyles)
        ' レベル 0
        ' name 
        _name.Style.Margins = New Thickness(1)
        _name.Style.Font = New Font("Calibri", 10, FontStyle.Bold)
        ' 説明
        _description.Style.Margins = New Thickness(1)
        _description.Style.Font = New Font("Calibri", 9, FontStyle.Italic)
        _description.Style.WordWrap = True
        ' img
        _img.Style.ImageScaling = ImageScaling.Scale
        _img.Style.ImageAlignment = ImageAlignment.CenterCenter
        ' レベル 1
        _product.Style.Font = New Font("Calibri", 10, FontStyle.Bold)
        _product.Style.Margins = New Thickness(2)
        _product.Style.HorizontalAlignment = Alignment.Center
        _product.Style.VerticalAlignment = Alignment.Center
    End Sub

    Public Overrides Sub SetValue(value As Object)
        If Node.level = 0 Then
            Dim row = DirectCast(Node.GetValue(), DataSet1.CategoriesRow)
            _name.Text = row.CategoryName
            _description.Text = row.Description
            Dim converter = New ImageConverter()
            If _img.Image IsNot Nothing Then
                _img.Image.Dispose()
                _img.Image = Nothing
            End If
            _img.Image = DirectCast(converter.ConvertFrom(row.Picture), Image)
            ' ルートパネルを設定します
            Child = _rw
        Else
            _product.Text = value.ToString()
            ' ルート要素を設定します
            Child = _product
        End If
    End Sub
End Class

Public Class ProductCustomNode
    Inherits CustomContentPresenter
    ' レベル 0
    Private _count As TextElement
    ' レベル 1
    Private _quantityPerUnit As TextElement
    Private _unitPrice As TextElement
    Private _unitInStock As TextElement
    Private _unitsOnOrder As TextElement
    Private _reorderLevel As TextElement
    Private _gp As GridPanel
    Private _eStyle As Style

    Public Sub New()
        ' レベル 0
        ' カテゴリでのカウント
        _count = New TextElement()
        _count.Style = New Style()
        _count.Style.Margins = New Thickness(2)
        ' レベル 1
        ' ラベルのスタイル
        Dim lStyle = New Style()
        lStyle.HorizontalAlignment = Alignment.Far
        lStyle.Margins = New Thickness(1)
        lStyle.Font = New Font("Calibri", 9, FontStyle.Regular)
        ' 要素スタイル
        _eStyle = New Style()
        _eStyle.Margins = New Thickness(1)
        _eStyle.Font = New Font("Calibri", 9, FontStyle.Regular)
        ' init要素
        _quantityPerUnit = New TextElement(_eStyle.Clone())
        _unitPrice = New TextElement(_eStyle.Clone())
        _unitInStock = New TextElement(_eStyle.Clone())
        _unitsOnOrder = New TextElement(_eStyle.Clone())
        _reorderLevel = New TextElement(_eStyle.Clone())
        ' テキスト要素のグリッドを初期化します
        _gp = New GridPanel()
        _gp.Columns.Add()
        ' ラベル
        _gp.Columns(0).Width = 100
        _gp.Columns.Add()
        ' テキスト
        _gp.Columns(1).Width = 120

        _gp.Rows.Add()
        ' ReorderLevel
        _gp(0, 0).Element = New TextElement(lStyle, "Reorder level:")
        _gp(0, 1).Element = _reorderLevel
        _gp.Rows.Add()
        ' UnitPrice
        _gp(1, 0).Element = New TextElement(lStyle, "Unit price:")
        _gp(1, 1).Element = _unitPrice
        _gp.Rows.Add()
        ' QuantityPerUnit
        _gp(2, 0).Element = New TextElement(lStyle, "Quantity per unit:")
        _gp(2, 1).Element = _quantityPerUnit

        _gp.Columns.Add()
        ' ラベル
        _gp.Columns(2).Width = 100
        _gp.Columns.Add()
        ' テキスト
        ' UnitsInStock
        _gp(0, 2).Element = New TextElement(lStyle, "Units in stock:")
        _gp(0, 3).Element = _unitInStock
        ' UnitsOnOrder
        _gp(1, 2).Element = New TextElement(lStyle, "Units on order:")

        _gp(1, 3).Element = _unitsOnOrder
    End Sub

    Public Overrides ReadOnly Property ToolTipText() As String
        Get
            Return String.Empty
        End Get
    End Property

    Public Overrides Sub SetStyle(styles As TreeNodeCellStyles)
        ' レベル 0
        _count.Style.HorizontalAlignment = Alignment.Center
        _count.Style.VerticalAlignment = Alignment.Center
        _count.Style.Font = New Font("Calibri", 11, FontStyle.Bold)
        ' レベル 1
        _unitPrice.Style.Font = New Font(_eStyle.Font, FontStyle.Bold)
        If _unitInStock.Text = "0" Then
            _unitInStock.Style.ForeColor = Color.Red
            _unitInStock.Style.Font = New Font(_eStyle.Font, FontStyle.Bold)
        End If
        If _unitsOnOrder.Text = "0" Then
            _unitsOnOrder.Style.ForeColor = Color.Red
            _unitsOnOrder.Style.Font = New Font(_eStyle.Font, FontStyle.Bold)
        End If
    End Sub

    Public Overrides Sub SetValue(value As Object)
        If Node.level = 0 Then
            Dim count = If(Node.HasChildren, Node.Nodes.Count, 0)
            _count.Text = count.ToString()
            Child = _count
        Else
            Dim row = DirectCast(Node.GetValue(), DataSet1.ProductsRow)
            _quantityPerUnit.Text = row.QuantityPerUnit
            _unitPrice.Text = row.UnitPrice.ToString("C")
            _unitInStock.Text = row.UnitsInStock.ToString()
            _unitsOnOrder.Text = row.UnitsOnOrder.ToString()
            _reorderLevel.Text = row.ReorderLevel.ToString()
            Child = _gp
        End If
    End Sub
End Class
public class CategoryCustomNode : CustomContentPresenter
{
    // レベル 0
    private TextElement _name;
    private TextElement _description;
    private ImageElement _img;
    private RowPanel _rw;
    // レベル 1
    private TextElement _product;

    public CategoryCustomNode()
    {
        // レベル 0
        // initテキスト要素
        // name
        _name = new TextElement();
        _name.Style = new Style();                    
        // 説明
        _description = new TextElement();
        _description.Style = new Style();
        _description.Width = 120;
        // イメージ要素をを初期化します。
        _img = new ImageElement();
        _img.Style = new Style();
        _img.Size = new Size(70, 50);            
        // テキスト要素のグリッドを初期化します。
        var cp = new ColumnPanel();
        cp.Children.Add(_name);
        cp.Children.Add(_description);
        // イメージのためにパネルを初期化します。
        _rw = new RowPanel();
        _rw.Children.Add(cp);
        _rw.Children.Add(_img);
        _rw.Style = new Style();
        _rw.Style.VerticalAlignment = Alignment.Center;
        // レベル 1
        _product = new TextElement();
        _product.Style = new Style();
    }

    public override string ToolTipText
    {
        get
        {
            return _name.Text;
        }
    }

    public override void SetStyle(TreeNodeCellStyles styles)
    {
        // レベル 0
        // name 
        _name.Style.Margins = new Thickness(1);
        _name.Style.Font = new Font("Calibri", 10, FontStyle.Bold);
        // 説明
        _description.Style.Margins = new Thickness(1);
        _description.Style.Font = new Font("Calibri", 9, FontStyle.Italic);
        _description.Style.WordWrap = true;
        // img
        _img.Style.ImageScaling = ImageScaling.Scale;
        _img.Style.ImageAlignment = ImageAlignment.CenterCenter;    
        // レベル 1
        _product.Style.Font = new Font("Calibri", 10, FontStyle.Bold);
        _product.Style.Margins = new Thickness(2);
        _product.Style.HorizontalAlignment = Alignment.Center;
        _product.Style.VerticalAlignment = Alignment.Center;
    }

    public override void SetValue(object value)
    {
        if (Node.Level == 0)
        {
            var row = (DataSet1.CategoriesRow)Node.GetValue();
            _name.Text = row.CategoryName;
            _description.Text = row.Description;
            var converter = new ImageConverter();
            if (_img.Image != null)
            {
                _img.Image.Dispose();
                _img.Image = null;
            }
            _img.Image = (Image)converter.ConvertFrom(row.Picture);
            // ルートパネルを設定します。
            Child = _rw;
        }
        else
        {
            _product.Text = value.ToString();
            // ルート要素を設定します。
            Child = _product;
        }
    }
}

public class ProductCustomNode : CustomContentPresenter
{
    // レベル 0
    private TextElement _count;
    // レベル 1
    private TextElement _quantityPerUnit;
    private TextElement _unitPrice;
    private TextElement _unitInStock;
    private TextElement _unitsOnOrder;
    private TextElement _reorderLevel;
    private GridPanel _gp;
    private Style _eStyle;

    public ProductCustomNode()
    {
        // レベル0
        // カテゴリでのカウント
        _count = new TextElement();
        _count.Style = new Style();
        _count.Style.Margins = new Thickness(2);
        // レベル01
        // ラベルのスタイル
        var lStyle = new Style();
        lStyle.HorizontalAlignment = Alignment.Far;
        lStyle.Margins = new Thickness(1);
        lStyle.Font = new Font("Calibri", 9, FontStyle.Regular);
        // 要素スタイル
        _eStyle = new Style();
        _eStyle.Margins = new Thickness(1);
        _eStyle.Font = new Font("Calibri", 9, FontStyle.Regular);
        // init要素
        _quantityPerUnit = new TextElement(_eStyle.Clone());
        _unitPrice = new TextElement(_eStyle.Clone());
        _unitInStock = new TextElement(_eStyle.Clone());
        _unitsOnOrder = new TextElement(_eStyle.Clone());
        _reorderLevel = new TextElement(_eStyle.Clone());
        // テキスト要素のグリッドを初期化します。
        _gp = new GridPanel();
        _gp.Columns.Add(); 
        // ラベル
        _gp.Columns[0].Width = 100;
        _gp.Columns.Add(); 
        // テキスト
        _gp.Columns[1].Width = 120;

        _gp.Rows.Add(); // ReorderLevel
        _gp[0, 0].Element = new TextElement(lStyle, "Reorder level:");
        _gp[0, 1].Element = _reorderLevel;
        _gp.Rows.Add(); // UnitPrice
        _gp[1, 0].Element = new TextElement(lStyle, "Unit price:");
        _gp[1, 1].Element = _unitPrice;
        _gp.Rows.Add(); // QuantityPerUnit
        _gp[2, 0].Element = new TextElement(lStyle, "Quantity per unit:");
        _gp[2, 1].Element = _quantityPerUnit;                        

        _gp.Columns.Add(); 
        // ラベル
        _gp.Columns[2].Width = 100;
        _gp.Columns.Add(); 
        // テキスト
        // UnitsInStock
        _gp[0, 2].Element = new TextElement(lStyle, "Units in stock:");
        _gp[0, 3].Element = _unitInStock;
        // UnitsOnOrder
        _gp[1, 2].Element = new TextElement(lStyle, "Units on order:");
        _gp[1, 3].Element = _unitsOnOrder;

    }

    public override string ToolTipText
    {
        get
        {
            return string.Empty; ;
        }
    }

    public override void SetStyle(TreeNodeCellStyles styles)
    {
        // レベル 0
        _count.Style.HorizontalAlignment = Alignment.Center;
        _count.Style.VerticalAlignment = Alignment.Center;
        _count.Style.Font = new Font("Calibri", 11, FontStyle.Bold);
        // レベル 1
        _unitPrice.Style.Font = new Font(_eStyle.Font, FontStyle.Bold);
        if (_unitInStock.Text == "0")
        {
            _unitInStock.Style.ForeColor = Color.Red;
            _unitInStock.Style.Font = new Font(_eStyle.Font, FontStyle.Bold);
        }
        if (_unitsOnOrder.Text == "0")
        {
            _unitsOnOrder.Style.ForeColor = Color.Red;
            _unitsOnOrder.Style.Font = new Font(_eStyle.Font, FontStyle.Bold);
        }
    }

    public override void SetValue(object value)
    {
        if (Node.Level == 0)
        {
            var count = Node.HasChildren ? Node.Nodes.Count : 0;
            _count.Text = count.ToString();
            Child = _count;
        }
        else
        {
            var row = (DataSet1.ProductsRow)Node.GetValue();
            _quantityPerUnit.Text = row.QuantityPerUnit;
            _unitPrice.Text = row.UnitPrice.ToString("C");                
            _unitInStock.Text = row.UnitsInStock.ToString();
            _unitsOnOrder.Text = row.UnitsOnOrder.ToString();
            _reorderLevel.Text = row.ReorderLevel.ToString();
            Child = _gp;
        }
    }
}

次のコードスニペットは、CustomContentPresenter プロパティを使用してカスタムノードを設定する方法を示します。

               
' カスタムノードを設定します 
C1TreeView1.Columns(0).CustomContentPresenter = New CategoryCustomNode()
C1TreeView1.Columns(1).CustomContentPresenter = New ProductCustomNode()
// カスタムノードを設定します。 
c1TreeView1.Columns[0].CustomContentPresenter = new CategoryCustomNode();
c1TreeView1.Columns[1].CustomContentPresenter = new ProductCustomNode();