【发布时间】:2019-07-19 20:45:32
【问题描述】:
在 form1 设计器中,我添加了一个树视图控件,并向其添加了一个根节点和一个子节点。并创建了绘画事件。
在form1代码中:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Test
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
AdvancedTreeView atv = new AdvancedTreeView();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
AdvancedTreeView.FillPolygonPoint(e);
}
}
}
AdvancedTreeView 类:
using System;
using System.Drawing;
using System.Windows.Forms;
public class AdvancedTreeView : TreeView
{
private static Image myimage;
public AdvancedTreeView()
{
DrawMode = TreeViewDrawMode.OwnerDrawAll;
ShowLines = false;
AlternateBackColor = BackColor;
}
public Color AlternateBackColor { get; set; }
protected override void OnDrawNode(DrawTreeNodeEventArgs e)
{
e.DrawDefault = true;
base.OnDrawNode(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 Image GetIcon(bool isExpanded)
{
return myimage;
}
private int GetTopNodeIndex(TreeNode node)
{
while (node.Parent != null)
node = node.Parent;
return Nodes.IndexOf(node);
}
public static void FillPolygonPoint(PaintEventArgs e)
{
// Create solid brush.
SolidBrush blueBrush = new SolidBrush(Color.Blue);
// Create points that define polygon.
Point point1 = new Point(0, 0);
Point point2 = new Point(20, 10);
Point point3 = new Point(0, 20);
Point[] curvePoints = { point1 , point2, point3 };
// Draw polygon to screen.
e.Graphics.FillPolygon(blueBrush, curvePoints);
myimage = new Bitmap(10,10,e.Graphics);
}
}
它正在进入 AdvancedTreeView 中的行:
DrawMode = TreeViewDrawMode.OwnerDrawAll;
但它永远不会进入 OnDrawNode。 我也试过 TreeViewDrawMode.OwnerDrawText 但它永远不会到达 OnDrawNode。
【问题讨论】:
-
因为在
Form1_Paint中,您调用了一个静态方法,它不知道OnDrawNode().您在ctor 中创建的avt实例刚刚创建并可供使用ctor 结束时的 GC,然后OnDrawNode()将永远不会在已处置的对象上被调用,也永远不会看到myimage静态字段。一般来说,您应该避免使用static方法,但无论如何,在这种情况下,您还需要将AdvancedTreeControl放在 UI 中的某个位置:使用设计器创建它或使用类似于this.Controls.Add(avt)的东西手动添加它 -
我知道我已经看过这个代码somewhere。 :)) 在您的表单构造函数中,您创建
AdvancedTreeView的本地实例,它的生命周期很短...... 1 行。相反,将AdvancedTreeView拖放到设计器中的表单上(如果您构建项目,它必须出现在工具箱中)。如果它有效,我希望我的原始答案值得一票。 :)))) -
您的
myImage仅在静态方法中设置。在构造函数中设置它,或者如果您想自己绘制它,只需删除该部分。 -
我的意思是你应该在构造函数中初始化你的图像,这样它就不会为空。像
myImage = new Bitmap(...)这样的东西。或者myImage = Resources.ArrowDown;如果您向项目添加了资源。 -
别着急,有时间我会写答案的。