0

Good day, I'm in the process of making a few custom controls based off of the standard controls in Visual Studio, but adding more functionality for Flat-style applications, which is what I normally make. All is going well with it as I have made quite a few functional controls already.

Upon having way too much work lost due to my Visual Studio crashing, I investigated and found the issue, well, the root of it at least.

Whenever I initialize a variable that can be modified using the design, say a Boolean that turns a border on or off (see pictures below), I would like to call the this.Invalidate() command during the Set event of said variable. But whenever I add the line of code and either click Build Solution or go into Design view, my Visual Studio freezes completely, and I find a Windows Error Reporting process running in Task Manager, this never returns an error which I could use.

Everytime I restart my Visual Studio straight into the project, a popup appears that tells me Visual Studio crashed due to an error and did not load any of the files I had open.

Please note, this happens on ANY of my custom controls and variables even if I set DrawMode = DrawMode.OwnerDrawFixed, and also adjusted all the SetStyle()

EDIT: Apologiez, Code samples:

[Category("Appearance")]
public bool HasBorder
{
    get
    {
        return HasBorder;
    }
    set
    {
        HasBorder = value;
        this.Invalidate();
    }
}

public vComboBoxList()
{
    Items = new List<object>();
    DataSource = new List<object>();
    SelectedItemColor = SystemColors.Highlight;
    HoverItemColor = SystemColors.HotTrack;
    BorderColor = SystemColors.ActiveBorder;
    HasBorder = false;
    ItemHeight = 16;
    BorderThickness = 2;
}
protected override void OnCreateControl()
{
    base.OnCreateControl();
}
protected override void OnPaint(PaintEventArgs e)
{
    Height = Items.Count * ItemHeight;
    if (Items.Count > 0)
    {
        foreach (object Item in Items)
        {
            if (Items.IndexOf(Item) == ItemOver)
                e.Graphics.FillRectangle(new SolidBrush(HoverItemColor), new Rectangle(0, Items.IndexOf(Item) * ItemHeight, Width, ItemHeight));
            else if (Items.IndexOf(Item) != ItemOver)
                e.Graphics.FillRectangle(new SolidBrush(BackColor), new Rectangle(0, Items.IndexOf(Item) * ItemHeight, Width, ItemHeight));
            e.Graphics.DrawString(Items.IndexOf(Item).ToString(), Font, new SolidBrush(ForeColor), new Point(4, Items.IndexOf(Item) * ItemHeight));
        }
    }
    if(HasBorder && BorderThickness != 0)
    {
        Rectangle _Top = new Rectangle(0, 0, Width, BorderThickness);
        Rectangle _Right = new Rectangle(Width, 0, -BorderThickness, Height);
        Rectangle _Left = new Rectangle(0, 0, BorderThickness, Height);
        Rectangle _Bottom = new Rectangle(0, Height, Width, -BorderThickness);
        e.Graphics.FillRectangles(new SolidBrush(BorderColor), new Rectangle[] { _Top, _Right, _Left, _Bottom });
    }
    base.OnPaint(e);
}

If I remove 'this.Invalidate()' from the 'set{}' it works perfectly.

Hurly
  • 37
  • 9
  • You have to distinguish [design time](http://stackoverflow.com/q/1166226/1997232), it's not the same as run-time. If you need further help consider to add related code to the post. Nobody is going to copy [code from pictures](http://meta.stackoverflow.com/q/303812/1997232). – Sinatr Jul 25 '16 at 07:59
  • Distinguishing seems like it limits the variable to either design or runtime? The variable should be able to be set during runtime and also while designing. I'm implementing a theme engine specific to my controls. While this is not needed, it would be nice to have "live" updates as oppposed to building and running the program the whole time. Oh and I removed the pictures. – Hurly Jul 25 '16 at 08:15

1 Answers1

0

This property setter has endless recursion:

[Category("Appearance")]
public bool HasBorder
{
    get
    {
        return HasBorder;
    }
    set
    {
        HasBorder = value; // will call setter again, which will call setter, which ...
        this.Invalidate();
    }
}

Change it to normal full property:

bool _hasBorder;
public bool HasBorder
{
    get { return _hasBorder; }
    set
    {
        _hasBorder = value;
        Invalidate();
    }
}
Sinatr
  • 20,892
  • 15
  • 90
  • 319
  • Something so simple, yet it works! :-D Thank you for your quick response and patience. I'll be honest, it is my first time making custom controls. Well, is my first time I ever needed to do so. – Hurly Jul 25 '16 at 08:33