views:

693

answers:

2

I want to wrap up a chunk of HTML render logic in a User Control. Then I want to pass a custom product object (title, thumbnail, id, etc.) to the UserControl that it can use when it renders. Ideally I want to use this in a repeater (or for loop) and pass the current custom product object into the UC.

Every example I've seen has been passing through strings on the UC tag but thats not really want I want to do as it means I'll have references everywhere that need updating should we add a new field that needs rendering.

Any ideas?

.Net 1 using VB.net (not my first choice for .net so go easy)

HTML example to get us going, this would be in the .ascx page:

<div>
  <h3><%= myProd.title %></h3>
  <img src="<%= myProd.thumbnail %>" />
  <p>
    <%= myProd.description %>
  </p>
</div>

UPDATE:

Ok so with some hacking around here is what I've come up with, its not working though, whats the missing piece of this puzzle?

Create a UserControl and add this to the code behind:

Public Class ProductRender
    Inherits System.Web.UI.UserControl

#Region " Web Form Designer Generated Code "

    'This call is required by the Web Form Designer.
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()

    End Sub

    'NOTE: The following placeholder declaration is required by the Web Form Designer.
    'Do not delete or move it.
    Private designerPlaceholderDeclaration As System.Object

    Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init
        'CODEGEN: This method call is required by the Web Form Designer
        'Do not modify it using the code editor.
        InitializeComponent()
    End Sub

#End Region

    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'Put user code to initialize the page here
    End Sub

    Private _product As productItem 

    Public Property myProd() As productItem 
        Get
            myProd = Me._product
        End Get
        Set(ByVal Value As productItem )
            Me._product = Value
        End Set
    End Property
End Class

In the UC ascx page I simply have the html above.

In the page that uses the UC I simply added the following for testing:

...usual ascx header stuff...
<%@ Register TagPrefix="ORC" TagName="productRender" Src="productRender.ascx" %>
<ORC:productRender id="Assetrender1" runat="server" asset="<%# getDummyProduct() %>" />

in the code behind I declare getDummyProduct as so:

Public Function getDummyProduct() As productItem
    getDummyProduct = New productItem( "DVD Player", "It plays DVDs!", "some_thumb.jpg", 30 )
End Function

Yet in my ascs page I get:"Object reference not set to an instance of an object"

Line 1:  <%@ Control Language="vb" AutoEventWireup="false" Codebehind="ProductRender.ascx.vb" Inherits="MyApp.ProductRender" TargetSchema="http://schemas.microsoft.com/intellisense/ie5" %>
Line 2:  <h3>
Line 3:  <%= myProd.title %>
Line 4:  </h3>
+1  A: 

I can think of several approaches.

I'd start by asking if you've ever done nested repeaters. If not, start there so that the next thing I'm about to say makes sense. (It's the concept that you need to get first.)

http://support.microsoft.com/kb/306154

You can create your User Control so that it can be databound, and use the concepts from the nested repeaters to datbind this control.

Another viable option would be to use the ItemDataBound event of the repeater to add a control in the code-behind.

http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.repeater.itemdatabound.aspx

A third option would be to create a server side function and put a method call to it in the ItemTemplate

<ItemTemplate>
     <%# DisplayProduct(DataBinder.Eval(Container,"DataItem.ProductId")) %>
</ItemTemplate>

...

Public Function DisplayProduct(ByVal ProductID as Integer) AS String
... logic goes here
End Function

All three will work, and there are pros and cons to each. The first option is probably the most "proper" but you'll want to do something you're comfortable with. Personally I'd try all three and see which one performs better.

------------ Added --------------------

I see... I think my wording may be confusing...

What I'm thinking about is making the ascx LOOK like a databound control...

What I've done in the past iscreate a userControl and expose a public property in it.

From the code behind of the ASCX (forgive me if the VB Syntax is off.. I haven't done VB for a few years):

Dim _RecordID as Integer = 0

Public Property RecordId
     Get
       Return _RecordID
     End Get
     Set(ByVal Calue as Integer)
       _RecordID = Value
     End Set
   End Property

and the in the Page_Load event of the ascx, put your code to load the data, just like any aspx page, using the RecordID property.

Then on the page that HOSTS the ASCX file

<%@ Register TagPrefix= = "dds"   TagName="ProductControl" ....  %>
    <ItemTemplate>
         <dds:ProductControl RecordId = '<%# (DataBinder.Eval(Container,"DataItem.ProductId")) %>'
    </ItemTemplate>
David Stratton
DataBinding a UserControl sounds to me more like the way to go, but back to the question, how do I do that? I've yet to find a simple example of how to do it.
Pete Duncanson
Since you can put anything you like inside a Repeater, why not just use the nested repeaters? I've been tossing this around in my head since I posted the answer, and the more I think of it, creating your own UserControl just adds to the complexity. I lke to keep things as simple as possible.Of course, you could create an ascx web user control and use the concepts from the first link in my answer to nest that inside the parent repeater.
David Stratton
But what about code reuse? I need to use the same block of HTML (for rendering products) on several pages. In Classic ASP I'd just use a function and pass it an object, thats pretty much what I'm after here.
Pete Duncanson
That last line David sounds exactly what I'm after, any examples you can give as I'm hacking away at this end but not getting much close to an answer :(
Pete Duncanson
I think I get the question now. I modified my answer and added a simplified example at the end.
David Stratton
Similar to where I got with my updated code in the original question, I know I'm close but its still not working. The DB searches have already been done in the framework we have, I just want to render them out by passing in the product object itself. However it would give me access to it in the ascx page, keep getting Object not found.
Pete Duncanson
A: 

Slaps forehead

Need to call DataBind in Page.OnLoad for the databinding to work, that explains why I was getting Object not found!

Pete Duncanson