2017-03-22 126 views
1

有没有办法自定义一个winform treeview来获取类似的东西?自定义树形视图

enter image description here

的目的是为具有由父项一种颜色一个定义一个三角形,而不是+/-图标来开发项目。

+1

'treeView1.DrawMode = TreeViewDrawMode.OwnerDrawAll;' – LarsTech

回答

1

使用TreeViewDrawMode.OwnerDrawText所以缩进将由TreeView进行调整。除此之外,你应该实施完整的绘画。

public sealed class AdvancedTreeView : TreeView 
{ 
    public AdvancedTreeView() 
    { 
     DrawMode = TreeViewDrawMode.OwnerDrawText; 
     ShowLines = false; 
     AlternateBackColor = BackColor; 
    } 

    public Color AlternateBackColor { get; set; } 

    protected override void OnDrawNode(DrawTreeNodeEventArgs e) 
    { 
     // background 
     Color backColor = (GetTopNodeIndex(e.Node) & 1) == 0 ? BackColor : AlternateBackColor; 
     using (Brush b = new SolidBrush(backColor)) 
     { 
      e.Graphics.FillRectangle(b, new Rectangle(0, e.Bounds.Top, ClientSize.Width, e.Bounds.Height)); 
     } 

     // icon 
     if (e.Node.Nodes.Count > 0) 
     { 
      Image icon = GetIcon(e.Node.IsExpanded); // TODO: true=down;false:right 
      e.Graphics.DrawImage(icon, e.Bounds.Left - icon.Width - 3, e.Bounds.Top); 
     } 

     // text (due to OwnerDrawText mode, indenting of e.Bounds will be correct) 
     TextRenderer.DrawText(e.Graphics, e.Node.Text, Font, e.Bounds, ForeColor); 

     // indicate selection (if not by backColor): 
     if ((e.State & TreeNodeStates.Selected) != 0) 
      ControlPaint.DrawFocusRectangle(e.Graphics, e.Bounds); 
    } 

    private int GetTopNodeIndex(TreeNode node) 
    { 
     while (node.Parent != null) 
      node = node.Parent; 

     return Nodes.IndexOf(node); 
    } 
} 

为了得到与截图类似的结果,只需设置颜色即可。

advancedTreeView1.BackColor = Color.DeepSkyBlue; 
advancedTreeView1.AlternateBackColor = Color.LightBlue; 
+0

我试过你的解决方案,但我可能错过了一些东西。我创建了一个'AdvancedTreeView',我用child添加了10个节点(之前用一个标准的'TreeView'测试过),但它只显示一个背景DeepSkyBlue着色。我在'OnDrawNode'中添加了一个断点,这个函数永远不会被调用。 –

+0

如果'DrawMode'只是'Normal',则调用它。 – taffer

+0

我修改了我的树,现在它正在工作(可能没有添加节点)。谢谢 –

1

只需在TreeView的属性中将DrawMode设置为“OwnerDrawAll”即可。请记住,你必须自己绘制它,并且必须处理TreeView_DrawNode事件。下面是事件处理的例子:

private void TreeListView_DrawNode(object sender, DrawTreeNodeEventArgs e) 
    { 
     if (e.Bounds.Height == 0) 
      return; 

     e.Graphics.FillRectangle(new SolidBrush((e.Node.Parent?.Index ?? e.Node.Index) % 2 == 0 ? Color.Blue : Color.Aqua), e.Bounds); 

     if (e.Node.Nodes.Count > 0) 
     { 
      if (!e.Node.IsExpanded) 
       e.Graphics.FillPolygon(Brushes.Red, 
        new[] 
        { 
         new PointF(e.Bounds.X + e.Bounds.Height/10, e.Bounds.Y + e.Bounds.Height/10), 
         new PointF(e.Bounds.X + e.Bounds.Height/10, e.Bounds.Y + e.Bounds.Height * 0.9f), 
         new PointF(e.Bounds.X + e.Bounds.Height, e.Bounds.Y + e.Bounds.Height/2) 
        }); 
      else 
       e.Graphics.FillPolygon(Brushes.Red, 
        new[] 
        { 
         new PointF(e.Bounds.X + e.Bounds.Height/10, e.Bounds.Y + e.Bounds.Height/10), 
         new PointF(e.Bounds.X + e.Bounds.Height, e.Bounds.Y + e.Bounds.Height/10), 
         new PointF(e.Bounds.X + e.Bounds.Height/2, e.Bounds.Y + e.Bounds.Height) 
        }); 
     } 
     e.Graphics.DrawString(e.Node.Text, new Font(FontFamily.GenericMonospace, e.Bounds.Height * 0.7f), 
      new SolidBrush(Color.Black), 
      new Rectangle(e.Bounds.X + e.Bounds.Height, e.Bounds.Y, e.Bounds.Width, e.Bounds.Height)); 
    } 
+0

是否有'TextRenderer.DrawText'和'e.Graphics.DrawString'之间的差? –

+0

有 - 看看这个:http://stackoverflow.com/questions/8283631/graphics-drawstring-vs-textrenderer-drawtextwhich-can-deliver-better-quality – MetaColon