I'm having some issues with custom code generation of Nested Objects as
described in the "Generation of Nested Objects" section of the
article "Customizing Code Generation in the .NET Framework Visual
Designers".

The example given is the DockPadding class property.  It is comprised of
two properties itself and is exposed in drill-down fashion in the property
grid simply with the setting of the DesignerSerializationVisibility.Content
attribute.

The "class-as-a-property" I'm trying to expose is a little more
complicated, but I was amazed at the amount of grief I had to go through to
get working what seemed so simple as setting an attribute according to the
article. Can anyone give me some insight as to why my situation differed so
much?

The "what should have been a simple dummy test-case" scenario:

A UserControl that contains a Label.  Instead of exposing properties like
LabelText and LabelForeColor, I want to encapsulate a majority of the Label
control's properties, and expose a few.  My example uses only one control
for simplicity, but think of several controls and several properties to
make this all worthwhile.

public class LabelField
{
  private Label _Control;

  public LabelField(Label labelcontrol)
  {
    _Control = labelcontrol;
  }

  [Category("Appearance"), Browsable(true), DefaultValue("")]
  public string Text
  {
    get {return _Control.Text;}
    set {_Control.Text = value;}
  }

  [Category("Appearance"), Browsable(true),
   DefaultValue(typeof(Color), "ControlText")]
  public Color BackColor
  {
    get {return _Control.BackColor;}
    set {_Control.BackColor = value;}
  }
}

Now, my UserControl does something along the lines of below (lots of code
omitted for brevity):

public class myUserControl : Windows.Forms.UserControl
{
  private Label myTestLabel;
  private LabelField objTestLabel;

  public myUserControl()
  {
    InitializeComponent();
    objTestLabel = new LabelField(myTestLabel);
  {

  public LabelField TestLabel
  {
    get {return objTestLabel;}
  }

}

A "Field" object is made, and hooked to the actual Label control within the
UserControl.  Then a public accessor property is made to the
Field "filter/wrapper/whatever" object instead of directly to the Label
control itself.  Now, only the two properties desired are exposed to the
UserControl's consumer, and you don't have consumers easily chaotically
manipulating the constituent controls of the usercontrol.

The consumer form of this usercontrol can reference the properties like so
(assuming it has an instance of the usercontrol called myUserControl1):

myUserControl1.TestLabel.BackColor = SystemColors.Window;
myUserControl1.TestLabel.Text = "Simple Test";

Everything seemed good so far until you look in the consumer project form's
designer, select the myUserControl1, then look at the "TestLabel" property
in the designer grid.  It is grayed out and doesn't allow for you to get at
the "BackColor" and "Text" properties.

Duh, Shawn's article to the rescue, I find the
DesignerSerializationVisibility.Content attribute just like it said for the
DockPadding class.  So I go back to my UserControl property and change it
to.

  [Browsable(true),
  DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
  public LabelField TestLabel
  {
    get {return objTestLabel;}
  }

Unfortunately, this little attribute is handily ignored by the designers.
The TestLabel property is still gray in the consumer project.

I tried all manner of things, until finally, I changed my
LabelField "filter/wrapper/whatever" class to derive from Component.

public class LabelField : System.ComponentModel.Component

Like magic, now the propertygrid in the consumer project for the
UserControl started walking down the nested LabelField property and showing
BackColor and Text.

In the article example, the DockPadding class is merely derived from
System.Object.  It didn't have to derive from
System.ComponentModel.Component for the
DesignerSerializationVisibility.Content attribute to work in the designers.

This is so ridiculous that I feel I must be missing something simple.

I don't understand..is it because my LabelField class harbours an internal
object of type "Control" that I have to derive from Component to get things
to work?

Any help in understanding all the "why" of this?

Thanks,

Jeff

You can read messages from the DOTNET archive, unsubscribe from DOTNET, or
subscribe to other DevelopMentor lists at http://discuss.develop.com.

Reply via email to