views:

303

answers:

1

I am writing a custom composite WebControl and want to expose styles of child controls it encapsulates to the ASP.NET designer. The code I currently have is similar to the skeleton below (which for simplicity only has one child control).

With the code below, I can see property "ChildPanelStyle" in the designer, but when I try to modify one of the properties (e.g. CssClass) in the designer, it immediately resets itself to its default value. It looks like the designer serialization isn't happening.

What am I doing wrong?

UPDATE

Adding a setter for the style property doesn't help and shouldn't be necessary. I've updated the sample with an additional style property that is managed directly by the custom control, rather than simply being the property of a child control.

The HeaderStyle property is persisted properly by the designer, but the ChildPanelStyle property isn't.

Of course I could manage all my styles like HeaderStyle, and apply them during rendering, but I'm hoping there's a simpler solution whereby child controls can take care of themselves, and I don't need any custom rendering.

public class MyControl : CompositeControl
{
    Panel myChildPanel;

    protected override void CreateChildControls()
    {
        myChildPanel = new Panel();
        this.Controls.Add(myChildPanel);
    }

    [
    Category("Style"),
    Description("Child panel style"),
    DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
    NotifyParentProperty(true),
    PersistenceMode(PersistenceMode.InnerProperty),
    ]
    public System.Web.UI.WebControls.Style ChildPanelStyle
    {
        get
        {
            EnsureChildControls();
            return this.myChildPanel.ControlStyle;
        }
    }

    [
    Category("Style"),
    Description("Header style"),
    DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
    NotifyParentProperty(true),
    PersistenceMode(PersistenceMode.InnerProperty),
    ]
    public System.Web.UI.WebControls.Style HeaderStyle
    {
        get
        {
            if (_headerStyle == null)
            {
                _headerStyle = new Style();
                if (IsTrackingViewState)
                    ((IStateManager)_headerStyle).TrackViewState();
            }
            return _headerStyle;
        }
    }
    private System.Web.UI.WebControls.Style _headerStyle;

    // ... overrides for save/load/tracking ViewState omitted 

    protected override void Render(System.Web.UI.HtmlTextWriter writer)
    {
        EnsureChildControls();
        base.Render(writer);
    }

}
+1  A: 

You've got no setter. Unfortunately, you can't directly set this.myChildPanel.ControlStyle, as it's a read-only property, so you'll have to set it's properties. Change your ChildPanelStyle property to the following:

[
Category("Style"),
Description("Child panel style"),
DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
NotifyParentProperty(true),
PersistenceMode(PersistenceMode.InnerProperty),
]
public System.Web.UI.WebControls.Style ChildPanelStyle
{
    get
    {
        EnsureChildControls();
        return this.myChildPanel.ControlStyle;
    }
    set
    {
        EnsureChildControls();
        this.myChildPanel.ControlStyle.BackColor = value.BackColor;
        this.myChildPanel.ControlStyle.BorderColor = value.BorderColor;
        this.myChildPanel.ControlStyle.BorderStyle = value.BorderStyle;
        this.myChildPanel.ControlStyle.BorderWidth = value.BorderWidth;
        this.myChildPanel.ControlStyle.CssClass = value.CssClass;
        this.myChildPanel.ControlStyle.Font.Bold = value.Font.Bold;
        this.myChildPanel.ControlStyle.Font.Italic = value.Font.Italic;
        this.myChildPanel.ControlStyle.Font.Name = value.Font.Name;
        this.myChildPanel.ControlStyle.Font.Names = value.Font.Names;
        this.myChildPanel.ControlStyle.Font.Overline = value.Font.Overline;
        this.myChildPanel.ControlStyle.Font.Size = value.Font.Size;
        this.myChildPanel.ControlStyle.Font.Strikeout = value.Font.Strikeout;
        this.myChildPanel.ControlStyle.Font.Underline = value.Font.Underline;
        this.myChildPanel.ControlStyle.ForeColor = value.ForeColor;
        this.myChildPanel.ControlStyle.Height = value.Height;
        this.myChildPanel.ControlStyle.Width = value.Width;
    }
}
David Morton
I tried adding a setter and it made no difference - which is what I expected. I updated my sample to show a case where a style managed directly by the property works fine in the designer, without a setter.
Joe
BTW wouldn't it be possible for the setter to update the ControlStyl using something like myChildPanel.ControlStyle.Reset(); myChildPanel.ControlStyle.MergeWith(value);
Joe