Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
How to subclass control?
Message
From
19/04/2008 19:30:01
 
 
To
10/04/2008 00:48:48
General information
Forum:
ASP.NET
Category:
Coding, syntax and commands
Environment versions
Environment:
C# 2.0
OS:
Windows XP SP2
Network:
Windows 2000 Server
Database:
MS SQL Server
Miscellaneous
Thread ID:
01184867
Message ID:
01311908
Views:
21
Hi Matt,

Sorry for taking so long to get back to you, but I've been out of town for awhile and haven't been online.

>the correct font appeared in the form textboxes at design-time, but the correct color only appeared at run-time. I made sure to "reset" the color property to get back to [DefaultValue], but the correct color still did not appear at design-time.

I think that might be a bug, or maybe it's by design, but I found that if you're overriding the ForeColor of a TextBox (and other controls as well), then you also need to do the BackColor ... without setting a DefaultValue for the BackColor, the ForeColor doesn't seem to work the way it should.

>It seems redundant to define a local class field with the desired color, and then also assigning the [DefaultValue] on the getter/setter to the same exact values. Looks like a good place for an oversight to happen when revising the code. Is there a good way to read the [DefaultValue] seeting from the local class field?

This isn't quite what you asked about, but I thought I'd just elaborate a bit on this topic and maybe it will make more sense. The [DefaultValue] attribute serves two purposes:

1) It allows the property to be easily Reset to it's Default Value from the Property Sheet.
2) It prevents the code that sets the default value from actually showing up in the InitializeComponent() method.

That second point is pretty important. Let's use a TextBox as an example, along with it's BackColor property. Say that you've not used the [DefaultValue] attribute in your TextBox, and simply set the value of the BackColor in your TextBox's constructor so that it looks like this:
public class MyTextBox : TextBox
{
	public MyTextBox()
	{
		this.BackColor = Color.DarkGreen;
	}
}
When you drop this TextBox onto a Form, the BackColor will be explicitly set in code to Color.DarkGreen in the InitializeComponent() method of the Form. Consequently, if you later decide to change the color in your MyTextBox class, you have to revisit every single Form that you ever dropped that TextBox on to change it to the new default value. Not good!

Now, let's look at the other scenario where you *do* include a property with a [DefaultValue] attribute, but you *don't* initialize that in the constructor. So, your class looks like this:
public class MyTextBox : TextBox
{
	public MyTextBox()
	{
	}
	
	[DefaultValue(typeof(System.Drawing.Color), "DarkGreen")]
	public override System.Drawing.Color BackColor
	{
		get {return base.BackColor;}
		set {base.BackColor = value;}
	}
}
When you drop MyTextBox on a Form now, it will default to a color of SystemColors.Control, which will be set in the InitializeComponent() method of the Form where you dropped MyTextBox onto, unless you go to the Property Sheet, right-click the BackColor and choose "Reset". Once you do this, the correct color appears for the TextBox on the Form, the setting of the BackColor property to SystemColors.Control in the InitializeComponent() method goes away and all looks fine ... until you decide to change the default to something else in your MyTextBox class ... since your TextBox doesn't initialize it's BackColor property in it's constructor, the Form goes back to displaying SystemColors.Control (even though it's not hard-coded in the InitializeComponent() method).

Suffice it to say that you simply must do both -- initialize it in the constructor and specify the [DefaultValue] attribute. Just something that you're going to have to remember to do!!

~~Bonnie





>Well, I think I've done it... What an education the whole process has been. I learned how to build my own sub-class library and reference it into my other projects. Also learned how to hack the Designer.cs file to re-assign the existing textboxes over to my class library, etc. My first control was a textbox that I can now set the font and forecolor on at the class-level so all textoxes on all forms will look the same. Next, I will do labels and command buttons.
>
>One comment - It seems redundant to define a local class field with the desired color, and then also assigning the [DefaultValue] on the getter/setter to the same exact values. Looks like a good place for an oversight to happen when revising the code. Is there a good way to read the [DefaultValue] seeting from the local class field?
>
>Also, the correct font appeared in the form textboxes at design-time, but the correct color only appeared at run-time. I made sure to "reset" the color property to get back to [DefaultValue], but the correct color still did not appear at design-time.
>
>I still contend it's about 4 times harder than VFP, and I really miss the visual and property sheet tool that VFP used,. But, it was fun figuring it all out.
>
>
>Anyway, here's my finished code for anyone else who might learn from this:
>(Please review and comment)
>
>
>
>namespace lms.BaseClasses
>{
>
>public class MyTextBox : mmTextBox //--Subclassing off of the MereMorals framework user controls
>{
>    private Font _font = new Font("Microsoft Sans Serif", 12.0F, FontStyle.Bold);
>    private Color _forecolor = Color.FromArgb(0, 255, 0);
>
>    public MyTextBox() //--Constructor
>    {
>        Font = _font;
>        ForeColor = _forecolor;
>    }
>
>    [DefaultValue(typeof(Font), "Microsoft Sans Serif, 12pt, style=Bold")]
>    public override Font Font
>    {
>       get { return base.Font; }
>       set { base.Font = value; }
>    }
>
>    [DefaultValue(typeof(Color),"0,255,0")]
>    public override Color ForeColor
>    {
>       get { return base.ForeColor; }
>       set { base.ForeColor = value; }
>    }
>
>}
>
>
>
>>>In my custom class library, when sublassing the .NET base classes to use in my project, can you not just hard-code property values at the class level?
>>>Something like this:
>>>
>>>public class MyTextBox : TextBox
>>>{
>>> this.forecolor = //-- color stuff here--//;
>>> this.font = //--font stuff here --//;
>>> this.size = //-- Size stuff here --//;;
>>>
>>>}

>>
>>Well, as you've seen, that doesn't work. Where it actually needs to go is in the constructor for the class. I guess I didn't explicitly include that in my example. Sorry.
>>
>>>I want to set the visual properties of my custom base classes so that I when I change them in my class library, it will make every form in my app automatically update the labels and texboxes to the new font and forecolor, backcolor etc. I want visual inheretence for these controls at the class lib level, not the propery sheet level.
>>
>>Consequently you have to do it the way I showed (getter and setter and the whole 9 yards). It won't work any other way.
>>
>>>I am coming from a VFP background where this matter was VERY easy.
>>
>>It's still easy Matt ... it's just different. It's really not that much work to add these properties as I've shown you and you really *do* need to do it like that, I kind of give an explanation as to why.
>>
>>~~Bonnie
>>
>>
>>
>>
>>
>>
>>>In my custom class library, when sublassing the .NET base classes to use in my project, can you not just hard-code property values at the class level?
>>>
>>>Something like this:
>>>
>>>public class MyTextBox : TextBox
>>>{
>>> this.forecolor = //-- color stuff here--//;
>>> this.font = //--font stuff here --//;
>>> this.size = //-- Size stuff here --//;;
>>>
>>>}
>>>
>>>It does not like the "this." and I tried "base.", but no luck either.
>>>
>>>The "getter" and "setter" example you gave (copied below) just seems like a ton of code just to set a few properties.
>>>
>>>I want to set the visual properties of my custom base classes so that I when I change them in my class library, it will make every form in my app automatically update the labels and texboxes to the new font and forecolor, backcolor etc. I want visual inheretence for these controls at the class lib level, not the propery sheet level.
>>>
>>>I am coming from a VFP background where this matter was VERY easy.
>>>
>>>
>>>
>>>
>>>>Holger,
>>>>
>>>>Here's the syntax for overriding properties and giving them the ability to be re-set to a Default in the Property Sheet:
>>>>
>>>>
>>>>public class MyTextBox : TextBox
>>>>{
>>>>    private string m_MyProperty;
>>>>
>>>>    public MyTextBox
>>>>    {
>>>>        this.m_MyProperty = "";
>>>>    }
>>>>
>>>>    [DefaultValue("")]
>>>>    public string MyProperty
>>>>    {
>>>>        get {return this.m_MyProperty;}
>>>>        set {this.m_MyProperty = value;}
>>>>    }
>>>>    [DefaultValue(typeof(Color), "Window")]
>>>>    public override Color BackColor
>>>>    {
>>>>        get {return base.BackColor;}
>>>>        set {base.BackColor = value;}
>>>>    }
>>>>    [DefaultValue(typeof(Color), "WindowText")]
>>>>    public override Color ForeColor
>>>>    {
>>>>        get {return base.ForeColor;}
>>>>        set {base.ForeColor= value;}
>>>>    }
>>>>}
>>>>
>>>>
>>>>Setting some of these properties doesn't always work as you would expect them to ... one that comes to mind is "Text" ... you may or may not have problems setting a default for that one, depending on which control you're sub-classing. Also, some properties aren't virtual and can't be overridden. For those properties, you can use "new" instead of "override".
>>>>
>>>>>And another question: Would the changes, made to these properties, appear in the formdesigner, if you drop the control there?
>>>>
>>>>Yes!!
>>>>
>>>>~~Bonnie
Bonnie Berent DeWitt
NET/C# MVP since 2003

http://geek-goddess-bonnie.blogspot.com
Previous
Next
Reply
Map
View

Click here to load this message in the networking platform