0

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.

9bjames
  • 31
  • 8
  • Hmmm, maybe your Grid property is being replaced? If the property should be allowed to be fully recreated then on your setter you must to hook to the PropertyChanged event (also unhook the previous GridProperties instance), else remove the setter to aviod problems (you can use property initializers for c# 6.0 or private setters for previous versions). – Gusman May 03 '16 at 22:08
  • I'm guessing you're right; I did what you recommended and hooked up the PropertyChanged event from inside Grid's setter, and now it seems to be working perfectly. Found it strange since I didn't think I was explicitly replacing Grid (apart from inside MyControl's constructor to initialize it), but either way glad it's working now! Thanks. – 9bjames May 04 '16 at 12:25
  • Glad it's working. It's very possible the designer is replacing your GridProperties, you can check the .designer.cs file, there should be the assignation. – Gusman May 04 '16 at 12:40

2 Answers2

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.

9bjames
  • 31
  • 8
0

Try inserting this after the constructor MyControl():

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

        grid.PropertyChanged += Redraw;
    }
Antonio S.F.
  • 101
  • 3