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

巧了我就是萌 提交于 2019-12-25 05:08:34

问题


C# - .Net4.0, Visual Studio 2010

For certain reasons I'm using a separate class to store some of my custom control's properties (properties to do with drawing a grid). This is causing some problems, since I'd like to be able to call "Invalidate()" any time these values are edited (either via the properties window, or during run-time), to automatically redraw the control. The best solution I could think of was to implement INotifyPropertyChanged within my "GridProperties" class, fire off a PropertyChanged event any time the relevant "set" accessors are called, and then subscribe to the PropertyChanged event handler from my control class to call a "Redraw" method (which just calls Invalidate()).

Here's a shortened version of my code so far.

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));
     }
}

What I expected: Redraw gets called any time Grid.Columns/ Grid.Rows/ Grid.ShowGridLines values are changed in any way (hopefully through properties window too).

What happens: Redraw never gets called, unless I do something like this, in an entirely new method in MyControl:

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

This works during run-time, but this defeats the point of using an event manager since I can just set the values then call Invalidate every time, and it doesn't help with any changes made through the properties window.

If anyone could give me a heads up on what I'm doing wrong or whether there's a better way, I'd really appreciate it. In all honesty I'm not even sure whether subscribing to a member's event manager is good practice or not.


回答1:


Thanks to Gusman for the solution. Instead of hooking up to PropertyChanged from within MyControl's constructor, I just hooked up to it from within Grid's setter, like so:

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

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

I can only assume something is replacing my GridProperties object somewhere. Either way, any time Grid's setter is accessed I just unhook/ and re-hook the PropertyChanged event manager, and now the screen updates whenever Grid's values are changed, whether by code or from the properties window.




回答2:


Try inserting this after the constructor MyControl():

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

        grid.PropertyChanged += Redraw;
    }


来源:https://stackoverflow.com/questions/37015016/c-sharp-custom-control-redraw-after-changing-a-member-objects-properties

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!