Templated data-bound server control design question

J

joe_s

Hello,
I am working on an n-tier .NET application. The presentation is through aspx
pages and custom data-bound server controls which use templates to separate
interface from content.

In all the samples I've seen regarding such controls, the templates are
instantiated in a class which inherits [Web]Control and implements
INamingContainer (here's the QuickStart source which demonstrates this:
http://samples.gotdotnet.com/quickstart/util/srcview.aspx?path=/quickstart/a
spplus/samples/webforms/ctrlauth/templates/Repeater2.src&file=CS\Repeater2.c
s&font=3). This class has all the properties which will eventually be shown
on the page. What I want to know is if there is a way to accomplish the same
thing without this class.

This might seem strange, but the reason I'd like to do this, is that I've
already got a class with the same properties in my business logic layer, and
I don't want to create another almost identical class. It would make
maintenance a nightmare. I can't use this class directly in the
ITemplate.InstantiateIn() method because it does not inherit Control, or
implement any interface, and it shouldn't.

I hope I made myself clear. If you have any suggestions or questions, please
do not hesitate to reply.

Thank you,
Joe
 
J

John Saunders

Perhaps you should explain why you have a class in your business logic layer
which you use for instantiating (presentation layer) templates.

--
John Saunders
Internet Engineer
(e-mail address removed)


joe_s said:
Hello,
I am working on an n-tier .NET application. The presentation is through aspx
pages and custom data-bound server controls which use templates to separate
interface from content.

In all the samples I've seen regarding such controls, the templates are
instantiated in a class which inherits [Web]Control and implements
INamingContainer (here's the QuickStart source which demonstrates this:
http://samples.gotdotnet.com/quicks...h/templates/Repeater2.src&file=CS\Repeater2.c
s&font=3). This class has all the properties which will eventually be shown
on the page. What I want to know is if there is a way to accomplish the same
thing without this class.

This might seem strange, but the reason I'd like to do this, is that I've
already got a class with the same properties in my business logic layer, and
I don't want to create another almost identical class. It would make
maintenance a nightmare. I can't use this class directly in the
ITemplate.InstantiateIn() method because it does not inherit Control, or
implement any interface, and it shouldn't.

I hope I made myself clear. If you have any suggestions or questions, please
do not hesitate to reply.

Thank you,
Joe
 
J

joe_s

I am not using that class, I can't because it doesn't inherit Control and
implement INamingContainer, and I know I shouldn't.

If you check out that link, you'll see that there is a class
(RepeaterItem.cs) which defines a data item with the data that will be
displayed on the page. If I implement my control in this way, I would need
to create such a class, but it would be virtually identical to my BL class,
except for the inheritance. Just to illustrate, here's an example:

// BL layer
class Car
{
int id;
string manufacturer;
string model;

// get/set properties here
}

public class CarCollection : ArrayList
{
public CarCollection() : base() {}
public CarCollection(ICollection c) : base(c) {}
}

class DBProcs
{
public CarCollection GetCarsFromDB()
{
CarCollection cc = new CarCollection();
// get data from db and fill the collection with Car objects //
return cc;
}
}

Let's say I want to display these items in by using a server control as I
explained in the original post. I would need to create the following class
in the presentation layer

// presentation
class CarItem : Control, INamingContainer
{
// everything's same as in the Car class above
// bad for maintenance
}

class MyServerControl : Control, INamingContainer
{
...
protected override void OnDataBinding(EventArgs e)
{
CarCollection cc = new CarCollection();
cc = GetCarsFromDB();
...
foreach(Car car in cc)
{
// I want to avoid the following
CarItem ci = new CarItem();
ci.Model = car.Model;
ci.Manufacturer = car.Manufacturer;

ItemTemplate.InstantiateIn(ci);
...
}
...
}
...
}

The syntax may not be 100% correct, but I hope you understand my problem
now.

John Saunders said:
Perhaps you should explain why you have a class in your business logic layer
which you use for instantiating (presentation layer) templates.

--
John Saunders
Internet Engineer
(e-mail address removed)


joe_s said:
Hello,
I am working on an n-tier .NET application. The presentation is through aspx
pages and custom data-bound server controls which use templates to separate
interface from content.

In all the samples I've seen regarding such controls, the templates are
instantiated in a class which inherits [Web]Control and implements
INamingContainer (here's the QuickStart source which demonstrates this:
http://samples.gotdotnet.com/quicks...h/templates/Repeater2.src&file=CS\Repeater2.c
s&font=3). This class has all the properties which will eventually be shown
on the page. What I want to know is if there is a way to accomplish the same
thing without this class.

This might seem strange, but the reason I'd like to do this, is that I've
already got a class with the same properties in my business logic layer, and
I don't want to create another almost identical class. It would make
maintenance a nightmare. I can't use this class directly in the
ITemplate.InstantiateIn() method because it does not inherit Control, or
implement any interface, and it shouldn't.

I hope I made myself clear. If you have any suggestions or questions, please
do not hesitate to reply.

Thank you,
Joe
 
J

John Saunders

Joe, simply have your CarItem class hold a reference to a Car instead of
duplicating all the properties:

foreach(Car car in cc)
{
if (ItemTemplate != null)
{
CarItem ci = new CarItem(car);
ItemTemplate.InstantiateIn(ci);
}
}
...

class CarItem : Control, INamingContainer
{
private Car m_Car;

public CarItem(Car car)
{
m_Car = car;
}

public Car DataItem
{
get {return m_Car;}
}
}
....

Your templates can then reference DataBinder.Evan(Container.DataItem,
"Manufacturer");


BTW, I'd separate the database access from the control. Give the control a
DataSource property of type CarCollection and let the page developer decide
what sort of car collection is wanted. You might even make the DataSource
property of type IEnumerable and let the control check at runtime whether
the enumerated items happen to be of type Car (or some derived class
thereof). That would allow you to use other collection types in the future -
a HashTable of cars, keyed on Owner, for instance.
--
John Saunders
Internet Engineer
(e-mail address removed)


joe_s said:
I am not using that class, I can't because it doesn't inherit Control and
implement INamingContainer, and I know I shouldn't.

If you check out that link, you'll see that there is a class
(RepeaterItem.cs) which defines a data item with the data that will be
displayed on the page. If I implement my control in this way, I would need
to create such a class, but it would be virtually identical to my BL class,
except for the inheritance. Just to illustrate, here's an example:

// BL layer
class Car
{
int id;
string manufacturer;
string model;

// get/set properties here
}

public class CarCollection : ArrayList
{
public CarCollection() : base() {}
public CarCollection(ICollection c) : base(c) {}
}

class DBProcs
{
public CarCollection GetCarsFromDB()
{
CarCollection cc = new CarCollection();
// get data from db and fill the collection with Car objects //
return cc;
}
}

Let's say I want to display these items in by using a server control as I
explained in the original post. I would need to create the following class
in the presentation layer

// presentation
class CarItem : Control, INamingContainer
{
// everything's same as in the Car class above
// bad for maintenance
}

class MyServerControl : Control, INamingContainer
{
...
protected override void OnDataBinding(EventArgs e)
{
CarCollection cc = new CarCollection();
cc = GetCarsFromDB();
...
foreach(Car car in cc)
{
// I want to avoid the following
CarItem ci = new CarItem();
ci.Model = car.Model;
ci.Manufacturer = car.Manufacturer;

ItemTemplate.InstantiateIn(ci);
...
}
...
}
...
}

The syntax may not be 100% correct, but I hope you understand my problem
now.

John Saunders said:
Perhaps you should explain why you have a class in your business logic layer
which you use for instantiating (presentation layer) templates.

--
John Saunders
Internet Engineer
(e-mail address removed)


joe_s said:
Hello,
I am working on an n-tier .NET application. The presentation is
through
aspx
pages and custom data-bound server controls which use templates to separate
interface from content.

In all the samples I've seen regarding such controls, the templates are
instantiated in a class which inherits [Web]Control and implements
INamingContainer (here's the QuickStart source which demonstrates this:
http://samples.gotdotnet.com/quicks...h/templates/Repeater2.src&file=CS\Repeater2.c
the
same layer,
and
 
J

joe_s

Wow, that's very simple. I don't know what I was thinking.

As for separating database access, that's exactly what I've done, the code
below was just quickly put together to illustrate the problem.

Thank you very much for your help, John.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,817
Latest member
DicWeils

Latest Threads

Top