Saturday, October 06, 2007

UnbindablePanel

To download the example solution click here: http://home.freeuk.com/eudoxus/JsWebSite.rar

[EDIT 03/11/2007] This link has been changed to include the code provided in my most recent Ajax-oriented post: ReOrderList replacement and other AJAX.NET Fun

I've been trying to get a Repeater to bind it's DataSource to contained controls for differing content. What I mean, there, is that if the DataSource has objects of different type I want to render a different data binding within the ItemTemplate depending on the type of data in the current DataItem. [Skip the next two paragraphs to get to the interesting bit.]

Having failed to try this by forcing Panel, PlaceHolder, MultiView/View and Wizard/StepTemplate from binding in anything other than a straightforward way (I hate it when future me can't follow younger me code!) I decided to try my latest trick...

Ok, I can't believe I didn't realise this before (or perhaps a more obvious solution - which, no, I still haven't discovered), but inheritting Panel and adding or overriding to get the functionality you want is just about the best way to make accessible, functional custom controls! They have data containers, can be bound, are supported by VS GUI and everyone understands them.

So, the situation is thus; I have bound a Repeater to a DataSource which provides an enumeration of objects which have different properties. This could be a random collection of DateTime, String and DataRow objects, or anything. Don't ask why, I just want to do it.

My solution is, essentially, to make a Panel which will not bind it's child controls if told not to. To decide whether it should or not, we simply check the class type, an identity or type field, property or namespace, etc.

So, first we inherit the Panel control:

public class UnbindablePanel : Panel

Then we have to provide a property which will determine whether or not the child controls found within the Panel will be databound:

private bool _allowChildBinding = true;
public virtual bool AllowChildBinding
{
get
{
return _allowChildBinding;
}
set
{
_allowChildBinding = value;
}
}

And finally, override the DataBindChildren() method to avoid the databinding if needed:

protected override void DataBindChildren()
{
if (AllowChildBinding)
{
base.DataBindChildren();
}
}

There is a little extra; in order to ensure the Panel is not visible at all, you might want to include a property/method combo to ensure the visibility matches the databound true/false value. This would stop any non-databound controls from being seen, but as such, is not absolutely necessary and is not the driving force behind this class.

To download the example solution click here: http://home.freeuk.com/eudoxus/JsWebSite1.rar