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

时间:2016-05-03 21:52:46

标签: c# custom-controls inotifypropertychanged

C# - .Net4.0,Visual Studio 2010

出于某些原因,我使用单独的类来存储我的一些自定义控件的属性(绘制网格的属性)。这导致了一些问题,因为我希望能够调用" Invalidate()"任何时候编辑这些值(通过属性窗口或在运行时),以自动重绘控件。我能想到的最好的解决方案是在我的" GridProperties"中实现INotifyPropertyChanged。 class,在相关的" set"中随时触发PropertyChanged事件。调用访问器,然后从我的控件类订阅PropertyChanged事件处理程序以调用" 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值以任何方式更改(希望通过属性窗口),也可以随时调用Redraw。

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

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

这在运行期间有效,但是这使得使用事件管理器失败了,因为我可以设置值,然后每次调用Invalidate,并且它对通过属性窗口所做的任何更改都没有帮助。

如果有人能让我了解我做错了什么,或者是否有更好的方式,我真的很感激。老实说,我甚至不确定是否订阅会员的活动经理是好的做法。

1 个答案:

答案 0 :(得分:1)

感谢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的值,屏幕都会更新。