473,397 Members | 1,974 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,397 software developers and data experts.

Control inheritance spoiled by Form designer.

The form designer adds unnecessary code to the section when using a
subclassed control.
I've reproduced this in VS.NET 2002 and VS.NET 2003 so it's pretty
fundamental.

Outline steps:
Create a VB project.
Create a subclass of a UI control, I used TextBox.
Add no code to the subclass.
Public Class Component1
Inherits System.Windows.Forms.TextBox
#Region " Component Designer generated code "
#End Region
End Class

Change the forecolour property only (Red in this example).
The designer adds code to the InitialiseComponent() method to set the new
forecolour.
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
'
'Component1
'
Me.ForeColor = System.Drawing.Color.Red
End Sub

Build it.

Create a VB windows form project.
Drag/drop a baseclass textbox.
Add reference to the DLL containing the control.
Add that to the toolbox.
Drag/drop a subclassed textbox.

All appears good.
But looking at the code it's not using inheritance !!

The form designer incorrectly (IMO) adds a line of code which duplicates the
code in the subclassed control's InitialiseComponent() which totally negates
the inheritance - I find this in the form's InitialiseComponent().

'Component11
'
Me.Component11.ForeColor = System.Drawing.Color.Red

If I distribute the control subclass as a separate assembly (dll) and then
update that dll, the compiled form has code that is hardwired to set the
colour of the instance of the control.
That's not right!
Because when I distribute a new version of the control with a different
forecolour, the code in the contorl's InitialiseComponent() might just as
well not be there - because the VB form has a line of code to set the colour
to that of the version of the component used at the time the form was
edited.
I can remove the offending code from the form's InitialiseComponent() and it
has no visual effect.
The colour is still as defined in the subclassed control.
I can change the control's forecolour, rebuild the dll and the form shows
the new forecolour.
There is still no offending code in the form InitialiseComponent()

Now we enter the twilight zone ...
In the form designer, if I move _either_ of the two textboxes, the offending
line of code reappears.
So, is this a known bug?
I don't want to have to put code in the subclassed control's Paint() method
for example, because that gets called far too often.

--

PAul
Nov 20 '05 #1
11 2227
I've now reproduced this in a C# form too, using the same VB subclass of
textbox, so it's pretty fundamental!

There is no reason as far as I can see that the form should have a copy of
the code from the subclasses control's InitialiseComponent() in the form's
InitialiseComponent() - because that overrides any change you may make in
the control class.
The form designer adds unnecessary code to the section when using a
subclassed control.
I've reproduced this in VS.NET 2002 and VS.NET 2003 so it's pretty
fundamental.

Outline steps:
Create a VB project.
Create a subclass of a UI control, I used TextBox.
Add no code to the subclass.
Public Class Component1
Inherits System.Windows.Forms.TextBox
#Region " Component Designer generated code "
#End Region
End Class

Change the forecolour property only (Red in this example).
The designer adds code to the InitialiseComponent() method to set the new
forecolour.
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent() '
'Component1
'
Me.ForeColor = System.Drawing.Color.Red
End Sub

Build it.

Create a VB windows form project.
Drag/drop a baseclass textbox.
Add reference to the DLL containing the control.
Add that to the toolbox.
Drag/drop a subclassed textbox.

All appears good.
But looking at the code it's not using inheritance !!

The form designer incorrectly (IMO) adds a line of code which duplicates the code in the subclassed control's InitialiseComponent() which totally negates the inheritance - I find this in the form's InitialiseComponent().

'Component11
'
Me.Component11.ForeColor = System.Drawing.Color.Red

If I distribute the control subclass as a separate assembly (dll) and then
update that dll, the compiled form has code that is hardwired to set the
colour of the instance of the control.
That's not right!
Because when I distribute a new version of the control with a different
forecolour, the code in the contorl's InitialiseComponent() might just as
well not be there - because the VB form has a line of code to set the colour to that of the version of the component used at the time the form was
edited.
I can remove the offending code from the form's InitialiseComponent() and it has no visual effect.
The colour is still as defined in the subclassed control.
I can change the control's forecolour, rebuild the dll and the form shows
the new forecolour.
There is still no offending code in the form InitialiseComponent()

Now we enter the twilight zone ...
In the form designer, if I move _either_ of the two textboxes, the offending line of code reappears.
So, is this a known bug?
I don't want to have to put code in the subclassed control's Paint() method for example, because that gets called far too often.

--

PAul

Nov 20 '05 #2
"PAul Maskens" <pm******@mvps.org> schrieb
The form designer adds unnecessary code to the section when using
a subclassed control.
I've reproduced this in VS.NET 2002 and VS.NET 2003 so it's pretty
fundamental.
[...]


It is not an inheritance issue. The designer is not interested in the
inheritance hierarchy. The reason why it creates the code is that the
property value (red) is not equal to default value of the property.

See also (didn't read the whole article):
http://msdn.microsoft.com/library/en...ustcodegen.asp

quote: "...If the current value of a property matches that default value,
code is not generated."

--
Armin

How to quote and why:
http://www.plig.net/nnq/nquote.html
http://www.netmeister.org/news/learn2quote.html

Nov 20 '05 #3
> It is not an inheritance issue.
Becauase it prevents us using inheritance to define visual characteristics,
and redefine in a new release of the assembly containing the subclass, it is
an inheritance issue.
The designer is not interested in the inheritance hierarchy. Exactly, so the designer is breaking inheritcance.
The reason why it creates the code is that the property value (red)
is not equal to default value of the property. What were they smoking when they designed that, then?
quote: "...If the current value of a property matches that default value,
code is not generated."

So the question then is, how do I define the new value in my subclass as the
new default?

It's not a show stopper, but I've been using OO languages for ten years and
this is unbelievable.
Nov 20 '05 #4
"PAul Maskens" <pm******@mvps.org> schrieb
It is not an inheritance issue. Becauase it prevents us using inheritance to define visual
characteristics, and redefine in a new release of the assembly
containing the subclass, it is an inheritance issue.
The designer is not interested in the inheritance hierarchy.

Exactly, so the designer is breaking inheritcance.


The designer creates code. Neither it changes your controls nor derives new
controls from yours, consequently it is impossible that it brakes
inheritance.
The reason why it creates the code is that the property value
(red) is not equal to default value of the property.

What were they smoking when they designed that, then?


Why? How can the designer know that the constructor of your control already
sets the value? It would have to analyse the source code or your control.
Not possible. Or, it would have to create the following code:

if not c.forecolor.equals(color.red) then
c.forecolor = color.red
end if

Wouldn't make sense, too, as we both know.
quote: "...If the current value of a property matches that default
value, code is not generated."

So the question then is, how do I define the new value in my subclass
as the new default?


As mentioned in the linked article, there's the DefaultValue attribute:

<System.ComponentModel.DefaultValue(GetType(Color) , "Red")> _
Public Overloads Property ForeColor() As Color
Get
Return MyBase.ForeColor
End Get
Set(ByVal Value As Color)
MyBase.ForeColor = Value
End Set
End Property

Seems to work.

It's not a show stopper, but I've been using OO languages for ten
years and this is unbelievable.


IMO it is not related to OO and especially inheritance at all.
--
Armin

Nov 20 '05 #5
Thanks for sticking with me on this, Armin.

<System.ComponentModel.DefaultValue(GetType(Color) , "Red")> _
Public Overloads Property ForeColor() As Color
Get
Return MyBase.ForeColor
End Get
Set(ByVal Value As Color)
MyBase.ForeColor = Value
End Set
End Property

Ouch !!
That's incredibly complex!
I was hoping this would work:

Function ShouldSerializeForeColor() As Boolean
ShouldSerializeForeColor = false
End Function

Like the C# example in the article.

Quote:
But what if the default value is not a simple one or this needs to be done more dynamically? This is often the case for values that are inherited from other components such as a parent Control. The dynamic case can be handled by adding a method of a certain signature. Using the example above, the code would look like this:

private bool ShouldSerializeText()
{
return Text != "OK";
}
By adding a method of the name ShouldSerialize<Property Name>, the code generation engine can ask the component if it would like the value to be serialized.
I can't get that to work in my simple test.
So I'm doing something wrong.
Nov 20 '05 #6
> if not c.forecolor.equals(color.red) then
c.forecolor = color.red
end if Why does the designer effectively do just that?
True, in this case it's analysing the value of the property.

What it does is if the current colour of my control subclass is not the
default colour of the parentclass, it writes a line of code into the form's
InitializeComponent().
Logically it's doing something like this (if parentclass was a property of a
control subclass) in the designer.

if not c.corefolor.equals(c.parentclass.forecolor) then
' write following code to the form InitializeComponent()
me.c.foreColor = color.green
end if

It would have to analyse the source code or your control.

In this case it's analysing the property values.
Nov 20 '05 #7
"PAul Maskens" <pm******@mvps.org> schrieb
Thanks for sticking with me on this, Armin.

<System.ComponentModel.DefaultValue(GetType(Color) , "Red")> _
Public Overloads Property ForeColor() As Color
This should have been

public OVERRIDES property....
Get
Return MyBase.ForeColor
End Get
Set(ByVal Value As Color)
MyBase.ForeColor = Value
End Set
End Property

Ouch !!
That's incredibly complex!
Well, attaching an attribute is not complex, but you can not attach an
attribute to a derived member, so you have to override it to get a procedure
to attach an attribute to.
I was hoping this would work:

Function ShouldSerializeForeColor() As Boolean
ShouldSerializeForeColor = false
End Function

Like the C# example in the article.

Quote:
But what if the default value is not a simple one or this needs to be
done more dynamically? This is often the case for values that are
inherited from other components such as a parent Control. The dynamic
case can be handled by adding a method of a certain signature. Using
the example above, the code would look like this:

private bool ShouldSerializeText()
{
return Text != "OK";
}
By adding a method of the name ShouldSerialize<Property Name>, the
code generation engine can ask the component if it would like the
value to be serialized.


I learn many new things in this thread. :-) This works for me:

Private Function ShouldSerializeForeColor() As Boolean
Return (Not Me.ForeColor.Equals(Color.Red))
End Function

But, _in addition_ you have to override the ForeColor property:

Public Overrides Property ForeColor() As Color
Get
Return MyBase.ForeColor
End Get
Set(ByVal Value As Color)
MyBase.ForeColor = Value
End Set
End Property
Why? The ForeColor property is part of the TextBoxBase class. The designer
looks at the members of the same type that contains the property to be
serialized to find the ShouldSerialize* function. It does find it, but it's
derived from the Control class. So, the designer calls
Control.ShouldSerializeForeColor. To change this behavior, you have to
override the property. Consequently the designer looks for
ShouldSerializeForeColor in your derived class.

--
Armin

Nov 20 '05 #8
"PAul Maskens" <pm******@mvps.org> schrieb
if not c.forecolor.equals(color.red) then
c.forecolor = color.red
end if Why does the designer effectively do just that?


It does *not* create this code. I wrote "it would have to create...".
True, in this case it's analysing the value of the property.

What it does is if the current colour of my control subclass is not
the default colour of the parentclass, it writes a line of code into
the form's InitializeComponent().
Logically it's doing something like this (if parentclass was a
property of a control subclass) in the designer.

if not c.corefolor.equals(c.parentclass.forecolor) then
' write following code to the form InitializeComponent()
me.c.foreColor = color.green
end if


What is a corefolor? ;-)) Anyway, I currently can not follow you. I wanted
to say that the designer compares the forecolor to the color specified in
the DefaultValueAttribute. If not equal => code is generated.
It would have to analyse the source code or your control.

In this case it's analysing the property values.


I'm not sure if I understand you. What I'm trying to say is that the
designer does not know if you already set Forecolor = Red within the
constructor. Consequently the designer must generate the code that you don't
want to be created.
--
Armin

Nov 20 '05 #9
Do you have any idea why the ShouldSerialize<property>() method isn't
working?
Can you see any mistake in what I tried in VB?

Function ShouldSerializeForeColor() As Boolean
ShouldSerializeForeColor = false
End Function
I am trying to use this approach. Because it talks exactly about what we are
doing, with a value inherited from a parent control.
Quote:
But what if the default value is not a simple one or this needs to be done
more dynamically? This is often the case for values that are inherited from
other components such as a parent Control. The dynamic case can be handled
by adding a method of a certain signature. Using the example above, the code
would look like this:

private bool ShouldSerializeText()
{
return Text != "OK";
}
By adding a method of the name ShouldSerialize<Property Name>, the code
generation engine can ask the component if it would like the value to be
serialized.
Nov 20 '05 #10
"PAul Maskens" <pm******@mvps.org> schrieb
Do you have any idea why the ShouldSerialize<property>() method
isn't working?
Can you see any mistake in what I tried in VB?
It works for me. See my answer to your other message.
Function ShouldSerializeForeColor() As Boolean
ShouldSerializeForeColor = false
End Function


I would not always set it to false. If you change the Color to Green within
the designer, the setting won't be stored.

--
Armin

Nov 20 '05 #11
That's fine.
We don't want colour changes to be made in the designer.
We are using an ObjectMode proeprty which says what kind of control it is
(in our application) and that drives the setting of appropriate colours
depending on control and application state.
Yes, we're ignoring windows standards, which I don't think is such a good
thing.
But it emulates an existing application's UI.

We planned to do this in a root class layer, inheriting directly from the
base controls, so that we could apply comany-wide standards there. Then
lower layers can add application specializations if necessary.
Designer support for this is critical, so we can reissue the libraries
separately from the application.
Nov 20 '05 #12

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: Jason Hickey | last post by:
Has there been a change in the way the UI designer handles winform inheritance in the 2003 version of visual studio. Consider the following (try it if you are using 2003 Everything seems to work...
1
by: tjmii | last post by:
I'm trying to use several web user controls on a page that share some common functionality. So, I want the user controls to inherit from a base class. I started off making this simple base class ...
1
by: Reza Nabi | last post by:
Bakground: I have a webform (LoadCtl.aspx) which loads the user control to a placeholder dynamically based on the ctlName querystring passed in the URL. Webform (LoadCtl.aspx) also passes a...
2
by: Mark | last post by:
I have basically a 2 part question: 1) is there a way to have a listview that can scroll, but hide the scrollbars. I know that sounds odd, but this is a touch screen app and there are "scroll...
2
by: Ray Cassick \(Home\) | last post by:
Since I got such good feedback from the Xml comments question I will ask this of the group as well. Is VS.NET 2005 handling the visual inheritance problems centered around controls and forms...
0
by: Marc Gravell | last post by:
Is there any (good) way to stop the designer trying to load a specific form/control when I double-click it in the solution explorer? Basically, I have some controls that either use generics or are...
0
by: fds | last post by:
Hello! I have a very specific question and that is about how to inherit a control for example the control System.Windows.Forms.TextBox without causing the environment to delete the control when...
0
by: Tony Johansson | last post by:
Hello! I have a very specific question and that is about how to inherit a visual control for example the control System.Windows.Forms.TextBox without causing the environment to delete the...
4
by: iKiLL | last post by:
Hi All I am Developing in C# with VS2005. I am Developing a Windows Mobile Forms Application with the CF2 My problem is that when the Input panel is displayed my screen does not
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.