Search code examples
c#asp.netuser-controlsmarkupabstract

Abstract ASP.NET User Control without recreating markup


I have the following control layout replicated several times in an ASP.NET application and would like to encapsulate the functionality in a user control (or server or composite control if necessary).

PSEUDO MARKUP

LISTBOX1 (Available Objects) > (Add Button) LISTBOX2 (Selected Objects)

Basically 2 listboxes with available objects in one listbox and selected objects in the other listbox (the type of these objects will change depending on use e.g. a collection of available and selected products)

Example usage: Add a listbox item from listbox1 to listbox2 via the add button (there are also buttons for adding all and going the other way from selected to available - these aren't shown for clarity) and the item is removed from listbox1 and placed in listbox2. Fairly straightforward - I'll call the control DualListbox.

I would like to do this:

DualListbox.ascx contains markup like this:

<asp:ListBox id="AvailableListBox"  runat="server"/> 
<asp:Button  id="AddItemtoSelected" runat="server"/> 
<asp:ListBox id="SelectedListBox"   runat="server"/>

and DualListBox.ascx.cs contains a series of abstract and non abstract functions, properties etc.

e.g

--We don't actually use CollectionBase but a class derived from it
protected abstract CollectionBase AvailableItems {get;set;}
protected abstract CollectionBase SelectedItems  {get;set;}


protected abstract void SaveContentsofAvailableListBox ();

private void FillAvailableListBox ()
{
   .....
   AvailableListBox.DataSource = AvailableItems;
   AvailableListBox.DataBind()
}
private void MoveItemfromAvailabletoSelectedListBox()
{
   ..Some code that takes item from available and puts it in selected.
}

Then I'd inherit from DualListbox.ascx e.g.

ConcreteDualListBox : DualListBox
{
    public override WidgetCollection AvailableItems {get;set;}
    public override void SaveContentsofAvailableListBox(){}; etc.etc.
}

The problem is that you can't inherit markup and so the markup in DualListBox is unavailable to the concrete class. I can define the markup in the concrete class but then to use functions like FillAvailableListBox in the base class I would have to pass the AvailableListBox control (and all the other controls) into the base class from the concrete class. Also for every concrete class the markup would have to be repeated (I could embed the common markup in each concrete class from another .ascx file I guess).

I would appreciate any suggestions on the correct way to go about defining such a control.

Apologies for the pseudocode - I'm doing this as a proof of concept at the moment.

Thanks, Rich.


Solution

  • I don't think you can do this directly with a user control. What you can do is break this down into 2 controls, a user control and a regular server control. Keep the markup in the user control and have the server control override the OnInit method and load the user control and add it as a child. All the logic with abstract methods can be embedded in the server control which can be inherited.