【问题标题】:Custom Control Doesn't Redraw In Designer Or When Running When A Property Is Changed自定义控件不会在设计器中重绘或在更改属性时运行
【发布时间】:2017-03-24 22:40:18
【问题描述】:

我正在创建一个基于 Panel 控件的自定义控件,并使用它在其中绘制一个矩形网格。我已将 Columns 和 Rows 作为属性,以便在将控件添加到表单后更改它们。但是,如果在设计器或表单代码中更改了值,则永远不会绘制矩形并且表单显示为空白。我在属性的 set 部分尝试了不同的建议,例如 this.Invalidate() 和 this.Refresh() 但我似乎仍然无法让它绘制新的矩形网格。我确定我只是在某个地方遗漏了一些东西。这是我正在使用的代码:

public class Pixel
{
    public Rectangle Bounds { get; set; }
    public bool IsOn { get; set; }
    public bool IsSelected { get; set; }
}

public class PixelGridControl : Panel
{
    private int columns = 99;
    private int rows = 63;
    private Pixel[,] pixels;
    private bool leftMouseIsDown = false;
    private bool rightMouseIsDown = false;

    public int Columns
    {
        get { return columns; }
        set
        {
            if (value > 0)
            {
                columns = value;
                CreatePixelGrid();
                this.Refresh();
            }
            else
            {
                throw new ArgumentOutOfRangeException("Columns", "Must be > 0");
            }
        }
    }
    public int Rows
    {
        get { return rows; }
        set
        {
            if (value > 0)
            {
                rows = value;
                CreatePixelGrid();
                this.Refresh();
            }
            else
            {
                throw new ArgumentOutOfRangeException("Rows", "Must be > 0");
            }
        }
    }

    public PixelGridControl()
    {
        this.DoubleBuffered = true;
        this.ResizeRedraw = true;

        CreatePixelGrid();
    }

    // adjust each column and row to fit entire client area:
    protected override void OnResize(EventArgs e)
    {
        int top = 0;
        for (int y = 0; y < Rows; ++y)
        {
            int left = 0;
            int height = (this.ClientSize.Height - top) / (Rows - y);
            for (int x = 0; x < Columns; ++x)
            {
                int width = (this.ClientSize.Width - left) / (Columns - x);
                pixels[x, y].Bounds = new Rectangle(left, top, width, height);
                left += width;
            }
            top += height;
        }
        base.OnResize(e);
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
        for (int y = 0; y < Rows; ++y)
        {
            for (int x = 0; x < Columns; ++x)
            {
                if (pixels[x, y].IsOn)
                {
                    e.Graphics.FillEllipse(Brushes.Gold, pixels[x, y].Bounds);
                    e.Graphics.DrawEllipse(Pens.Goldenrod, pixels[x, y].Bounds);
                }
                else
                {
                    e.Graphics.FillRectangle(Brushes.Black, pixels[x, y].Bounds);
                    e.Graphics.DrawRectangle(Pens.White, pixels[x, y].Bounds);
                }
            }
        }
        base.OnPaint(e);
    }
    private void CreatePixelGrid()
    {
        // initialize pixel grid:
        pixels = new Pixel[Columns, Rows];
        for (int y = 0; y < Rows; ++y)
        {
            for (int x = 0; x < Columns; ++x)
            {
                pixels[x, y] = new Pixel();
            }
        }
    }
}

【问题讨论】:

    标签: c# .net winforms


    【解决方案1】:

    问题是当RowsColumns 更改时,您不会填充网格单元边界,因此它们仍然是Rectangle.Empty

    要解决此问题,请将代码从 OnResize 移至单独的方法:

    private void UpdatePixelGrid()
    {
        // adjust each column and row to fit entire client area:
        int top = 0;
        for (int y = 0; y < Rows; ++y)
        {
            int left = 0;
            int height = (this.ClientSize.Height - top) / (Rows - y);
            for (int x = 0; x < Columns; ++x)
            {
                int width = (this.ClientSize.Width - left) / (Columns - x);
                pixels[x, y].Bounds = new Rectangle(left, top, width, height);
                left += width;
            }
            top += height;
        }
    }
    

    并从OnResizeCreatePixelGrid 调用它:

    protected override void OnResize(EventArgs e)
    {
        UpdatePixelGrid();
        base.OnResize(e);
    }
    
    private void CreatePixelGrid()
    {
        // initialize pixel grid:
        pixels = new Pixel[Columns, Rows];
        for (int y = 0; y < Rows; ++y)
        {
            for (int x = 0; x < Columns; ++x)
            {
                pixels[x, y] = new Pixel();
            }
        }
        UpdatePixelGrid();
    }
    

    【讨论】:

    • 我想这可能是一个我错过设置的简单属性。谢谢!
    猜你喜欢
    • 2011-08-22
    • 2013-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-20
    • 1970-01-01
    相关资源
    最近更新 更多