Prevent Winforms Designer from Generating Property Values for Inherited Controls
Asked Answered
E

4

6

I have a custom DataGridView, let's say as such:

public MyGridView : DataGridView
{
    public MyGridView()
    {
         BackgroundColor = Color.Red;
    }
}

Now, when I use this control in a project using the designer, for some reason it feels a need to also set the property in the designer.cs file.

So in the designer file, I would have:

this.MyGridView1.BackgroundColor = System.Drawing.Color.FromArgb((byte)(int)255, (byte)(int)0, (byte)(int)0);

The problem me with this is that it prevents me from being able to change the color in the constructor of my MyGridView, without having to go through all the forms in which I used to control and change it per instance, rendering my custom control useless.

With some properties which offer a virtual getter, this is no problem, but most properties do not have it.

How can I prevent the designer from generating this code?

Ethnic answered 30/12, 2013 at 9:14 Comment(4)
Decorate property with DefaultValue attribute.Sacker
@NikolaMarkovinović These are not properties I've created, these are properties inherited from DataGridView (.e.g BackgroundColor). Where would I add the attribute?Ethnic
Serves me right for not reading the question throughly. I don't think that there is an acceptable solution. You might hide original property as they did in this answer dealing with inherited ComboBox. Again, my apologies.Sacker
@NikolaMarkovinović No problem! At least you gave it some attention :) The question you linked is a possible workaround, but it only works for constable values. Is there a way to assign a default value attribute to non-constable value types?Ethnic
D
13

I should emphasize that this isn't normally the way you do this, the [DefaultValue] attribute is normally the correct choice. But you are working with a property of type Color, it is not simple to write the attribute for that in a flexible way. The arguments you can pass to an attribute constructor can be only a select few data types, Color isn't one of them. You'd have to craft a string that ColorConverter can understand, that's both ugly and hard to maintain.

PropertyGrid has a secondary way of providing defaults for "difficult" properties, it will also look for specially named private members in the class. Given a property named "Xxxx", it looks for the following:

  • DefaultXxxx, a property with just a getter that returns the default value
  • ResetXxxx(), a method that can run when the user selects the Reset context menu item
  • ShouldSerializeXxxx(), a method that should return false if the value of the property should not be persisted.

Which makes this code work:

public class MyGridView : DataGridView {
    public MyGridView() {
        this.BackgroundColor = DefaultBackgroundColor;
    }
    public new Color BackgroundColor {
        get { return base.BackgroundColor; }
        set { base.BackgroundColor = value;  }
    }
    private bool ShouldSerializeBackgroundColor() {
        return !this.BackgroundColor.Equals(DefaultBackgroundColor);
    }
    private void ResetBackgroundColor() {
        this.BackgroundColor = DefaultBackgroundColor;
    }
    private static Color DefaultBackgroundColor {
        get { return Color.Red; }
    }
}

Note that the ResetBackgroundColor() method is not actually necessary since no special effects are required when the user resets the property, I just included it for completeness.

Denn answered 30/12, 2013 at 11:8 Comment(3)
How would you go about doing this for something another level deep like the AlternatingRowsDefaultCellStyle.BackColor property?Arbor
This approach works for any property of type Color, BackgroundColor was just an example. Changing the DataGridView.AlternatingRowsDefaultCellStyle property just takes a lot more work since you don't just have to change the Color, you also have to provide the DataGridViewCellStyle instance. Click the Ask Question button to get help.Denn
The ResetXxxx() and ShouldSerializeXxxx() methods are documented here. Did someone find official documentation for the DefaultXxxx property mechanism?Depurative
D
3

There is a simpler way to assign DefaultValue to Color:

public class MyGridView : DataGridView
{
    public MyGridView()
    {
        BackgroundColor = Color.Red;
    }

    [DefaultValue(typeof(Color), "Red")]
    public new Color BackgroundColor
    {
        get { return base.BackgroundColor; }
        set { base.BackgroundColor = value; }
    }
}
Discursive answered 28/1, 2014 at 9:15 Comment(0)
E
2

Try using InitLayout instead and DesignMode. You can't use DesignMode in the ctor, but after the control is constructed you can access the Designmode property correctly to set the colour. Note: this will not be styled in the designer, just at run time.

public class MyGridView : DataGridView
{

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

        if (!DesignMode)
            BackgroundColor = Color.Red;
    }
}
Eastman answered 30/12, 2013 at 9:58 Comment(1)
Thanks, this is a reasonable compromise. I am using it instead in the OnHandleCreated method, for reasons specific to my project.Ethnic
A
0

If needs are simple and design appearance is no issue, try writing an extension or two, e.g.,

public static class Extensions
{
    public static void ApplyStyle( this DataGridView dataGridView )
    {
        dataGridView.RowHeadersVisible = false;
        ...
    }
}
Anopheles answered 13/4, 2015 at 14:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.