C# 自定义控件 - 更改成员对象的属性后重绘

C# custom control - Redraw after changing a member object's properties

C#-.Net4.0,Visual Studio2010

出于某些原因,我使用单独的 class 来存储我的一些自定义控件的属性(与绘制网格有关的属性)。这导致了一些问题,因为我希望能够在编辑这些值时随时调用 "Invalidate()"(通过属性 window,或在 运行 期间),以自动重绘控件。我能想到的最佳解决方案是在我的 "GridProperties" class 中实现 INotifyPropertyChanged,在调用相关 "set" 访问器时触发 PropertyChanged 事件,然后订阅 PropertyChanged 事件处理程序从我的控件 class 调用 "Redraw" 方法(只调用 Invalidate()).

到目前为止,这是我的代码的简化版本。

class MyControl : Control
{
    [Browsable(true)]
    public GridProperties Grid { get; set; }

    public MyControl()
    {
        Grid = new GridValues();
        Grid.Columns = 4;
        Grid.Rows = 4;
        Grid.ShowGridLines = true;

        Grid.PropertyChanged += Redraw;
    }

    private void Redraw (object sender, PropertyChangedEventArgs e)
    {
        Invalidate();
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);

        //draw gridlines
        //draw columns/ rows
    }
}


class GridProperties : INotifyPropertyChanged
{
    private int columns;
    private int rows;
    private bool showGridLines;

    public int Columns
    {
        get { return columns; }
        set
        {
            if (columns != value)
            {
                columns = value;
                NotifyPropertyChanged("Columns");
            }
        }
    }

    public int Rows...
    //same kinda deal for rows & showGridLines

    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(string info)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(info));
     }
}

我所期望的:任何时候都会调用重绘 Grid.Columns/ Grid.Rows/ Grid.ShowGridLines 值以任何方式更改(希望也通过属性 window)。

会发生什么:Redraw 永远不会被调用,除非我在 MyControl 中用一个全新的方法做这样的事情:

Grid.PropertyChanged += Redraw;
Grid.ShowGridLines = false;

这在 运行 时间内有效,但这违背了使用事件管理器的意义,因为我每次都可以设置值然后调用 Invalidate,并且它对通过属性 window.

如果有人能提醒我我做错了什么或者是否有更好的方法,我将不胜感激。老实说,我什至不确定订阅会员的活动管理器是否是一种好的做法。

感谢 Gusman 提供的解决方案。我没有从 MyControl 的构造函数中连接到 PropertyChanged,而是从 Grid 的 setter 中连接到它,如下所示:

private GridProperties grid;
[Browsale(true)]
public GridProperties Grid
{
    get
    {
         return grid;
    }
    set
    {
        if(grid! = null)
            grid.PropertyChanged -= Redraw;

        grid = value;
        grid.PropertyChanged += Redraw;
    }
}

我只能假设某些东西正在某处替换我的 GridProperties 对象。无论哪种方式,只要 Grid 的 setter 被访问,我只需取消挂钩/重新挂钩 PropertyChanged 事件管理器,现在只要 Grid 的值发生变化,屏幕就会更新,无论是通过代码还是从属性 window。

尝试在构造函数 MyControl() 之后插入:

protected override void OnCreateControl()
    {
        base.OnCreateControl();

        grid.PropertyChanged += Redraw;
    }