Greetings, y'all.
I'm wanting to create a templated Web control that will allow the user
to specify a template. In my Web control, I'd like to populate a
SqlDataReader with a database table - the template would be there to
allow the user to customize the output of the databse information. For
example, I'd like to be able to have the user enter:
<mynamespace:mycontrol runat="server">
<ItemTemplate>
<b>Purchase Order Number:</b> <%# Container.PONumber %><br>
<b>Date Filled:</b> <%# Container.DateFilled %>
<p>
</ItemTemplate>
</mynamespace:mycontrol>
Or something like that. The Web control would then read in the template
and have public properties named PONumber and DateFilled that would
return the PONumber and DateFilled columns from the SqlDataSet.
Ok, so I started off trying to get a rather simple example done, just
employing simple template features. I created a Web control that
exposed a public property named ItemTemplate that was of type ITemplate:
ITemplate _itemTemplate;
[TemplateContainer(typeof(mycontrol))]
public ITemplate ItemTemplate
{
get { return _itemTemplate; }
set { _itemTemplate = value; }
}
then in the CreateChildControls I added the following code:
protected override void OnPreRender(EventArgs e2)
{
SqlDataReader dr = BusinessComponent.GetPurchaseInfo(...);
while (dr.Read())
{
if (_itemTemplate != null)
{
_itemTemplate.InstantiateIn(this);
}
}
}
compile the control, and view a test page with the following code:
<mynamespace:mycontrol runat="server">
<ItemTemplate>
Foobar<br>
</ItemTemplate>
</mynamespace:mycontrol>
I get as output a number of Foobars, depending on how many records were
returned by the GetPurchaseInfo method of my business logic component.
Great! I'm on my way to using templates.
Now, when trying to use databound information in my template, I'm
running into stumbling blocks. According to Professional ASP.NET's
chapter 18 (~pg. 930) I can add a DataItem public, read-only property to
my compiled control like so:
Object _dataItem;
public Object DataItem
{
get { return _dataItem; }
}
and then, in my CreateChildControls() method, I can do:
protected override void OnPreRender(EventArgs e2)
{
SqlDataReader dr = BusinessComponent.GetPurchaseInfo(...);
while (dr.Read())
{
if (_itemTemplate != null)
{
_dataItem = dr["PONumber"].ToString();
_itemTemplate.InstantiateIn(this);
}
}
}
Now, if I do:
<mynamespace:mycontrol runat="server">
<ItemTemplate>
PO Number = <%# Container.DataItem %><br>
</ItemTemplate>
</mynamespace:mycontrol>
I *should* get a listing of each PO Number, but instead I just get the
literal text displayed:
PO Number -
PO Number -
PO Number -
...
That is, the control is not displaying the databound content. Why? It
is obviously matching up the Container.DataItem property in my compiled
control - for example, if I change it to Container.Foo it complains that
there is no public property Foo in my compiled control class. What in
the world am I missing? I've been banging my head against the wall on
this problem for the last 4 hours, trying a myriad of things, but none
of them successful.
Also, while I have your attention, let me ask if there are any good
references on building compiled Web controls. So far I've been using Pro
ASP.NET and Microsoft's .NET documentation, both which are either
lacking or difficult to use. Any good tomes out there? Thanks!
Scott Mitchell
mitchell@4...
http://www.4GuysFromRolla.com/
http://www.ASPMessageboard.com/
http://www.ASPFAQs.com/
* When you think ASP, think 4GuysFromRolla.com!