Inheriting from a System.Web.UI.UserControl base class

Sean Anderson picture Sean Anderson · Feb 28, 2011 · Viewed 8.6k times · Source

First off, I am wondering if this is possible. I read slight grumblings around the internet about this, but I was not entirely sure.

My scenario: I have a base chart class which has some methods which all charts should have.

public partial class BaseChart : System.Web.UI.UserControl
{
    public BaseChart()
    {
    }

    public void ToggleLegend()
    {
        Chart1.Legends[0].Enabled = !Chart1.Legends[0].Enabled;
    }
}

There is also some mark-up for this BaseChart -- setting background colors, etc. All charts which inherit BaseChart should use this starting mark-up and be able to build upon it.

I would then like to do this:

public partial class HistoricalLineChart : BaseChart
{
    public HistoricalLineChart()
        : base()
    {
    }

    public HistoricalLineChart(int reportID)
        : base()
    {
        Chart1.Titles[0].Text = "Hello World";
    }
 }

where HistoricalLineChart is a web user control with no mark-up e.g. "HistoricalLineChart.ascx"

The problem is that Chart1 is undefined when in HistoricalLineChart's scope. Is there something that I am missing here?

Thanks.

Answer

Jamie Treworgy picture Jamie Treworgy · Feb 28, 2011

Though usually one ends up just making a custom control in this situation (as the other answer suggest), and this is good for many reasons, there are a couple other approaches that may be useful in situations where complicated markup makes a server control infeasible.

1) Create a base class that has all the functionality common to your implementations and inherits UserControl. If you really want to include markup as part of the base class, you could put it in a separate usercontrol with no code, and load it from the abstract class, though this seems a little ugly. If the markup that is shared is simple, though, just render it from code instead.

public abstract class MyUserControl: UserControl
{
     public Chart Chart1;
     public void ToggleLegend()
    {
        Chart1.Legends[0].Enabled = !Chart1.Legends[0].Enabled;
    }
    public override void CreateChildControls()
    {
        Controls.Add(Page.LoadControl("path/to/mymarkup/control"));
        // or add them in code
        BuildBaseControls();
    }
}

2) Create UserControl implementations that inherit MyUserControl instead of UserControl, and add the markup

public partial class HistoricalLineChart : MyUserControl
{
    public HistoricalLineChart(int reportID)
        : base()
    {
        Chart1.Titles[0].Text = "Hello World";
    }
}

You could also create an interface that describes any controls that should appear in the markup and implement that. This is nice because it gives you a construct that is applicable to either a UserControl (where the controls are defined in markup) or a WebControl (where the controls are created in code), leaving the actual details of the markup to each implementation, but letting you share the functionality.