views:

137

answers:

1

Hi, I need help on how to handle button clicks in an ASP.NET repeater's item when the record on which the item is based is identified by a primary key spanning multiple columns.

The backgrounds:

The page I'm talking about fetches a Complaint, which is an object with some properties, from the database and displays its properties to the user.

One of this properties is Escalations, which is a System.Collections.Generic.List<Escalation> object.

The Escalation object is merely an in-code representation of the following SQL table:

create table [escalations]
(
    [complaint_id] int not null,
    [escalation_group_id] varchar (50) not null
    [escalation_date] datetime not null,
    [escalation_text] text not null,
    [response_date] datetime null,
    [response_text] text null,

    constraint [pk_escalations] primary key ([complaint_id], [escalation_date]),
    constraint [fk_complaints] foreign key ([complaint_id]) references [complaints].([complaint_id]),
    constraint [fk_escalation_groups] foreign key ([escalation_group_id]) references [escalation_groups].([escalation_group_id])
)

To display the list of Escalations I choose to use a System.Web.UI.WebControls.Repeater, because I need a complex layout, so I went with the following code (it's a stripped down version of the actual code to improve readability, e.g. the "Reply to this complaint" part is placed in a modal pop-up, there are validators and so on):

<h2>Complaint #<asp:literal id="complaint_id" runat="server" /></h2>

<asp:repeater id="escalations" runat="server">
    <itemtemplate>
        <h3>Escalation date</h3>
        <p><%# DataBinder.Eval(Container.DataItem, "complaint_date", "{0:yyyy-MM-dd}") %></p>

        <h3>Complaint text</h3>
        <p><%# DataBinder.Eval(Container.DataItem, "complaint_text") %></p>

        <asp:panel id="response_panel" visible='<%# DataBinder.Eval(Container.DataItem, "response_date") == null ? false : true %>' runat="server">
            <h3>Response date</h3>
            <p><%# DataBinder.Eval(Container.DataItem, "response_date", "{0:yyyy-MM-dd}") %></p>

            <h3>Response text</h3>
            <p><%# DataBinder.Eval(Container.DataItem, "response_text") %></p>
        </asp:panel>

        <asp:panel id="reply_panel" visible='<%# DataBinder.Eval(Container.DataItem, "response_date") == null ? true : false %>' runat="server">
            <h3>Reply to this complaint</h3>
            <p><asp:textbox id="complaint_response" textmode="multiline" runat="server" /></p>
            <p><asp:button id="send_response" text="Send response" onclick="SendResponse" runat="server" /></p>
        </asp:panel>
    </itemtemplate>
</asp:repeater>

When the user clicks on the send_response button, I need to update the corresponding Escalation, and I'm at loss on how to identify the correct one.

protected void SendResponse(Object sender, EventArgs e)
{
    // ?!?!
}

Getting the complaint_id is not a big problem, I can save it in the ViewState since it's the same for every Escalation.

If the Escalation would have been identified by a primary key built on a single column, I could have specified a CommandArgument on the send_response button, however since the primary key is formed by the complaint_id and escalation_date columns, it's not possible to do it.

I even found around solutions involving the bounding of the fields to controls like System.Web.UI.WebControls.Label or System.Web.UI.WebControls.Literal, but since the field I need to pass is a DateTime, I don't know how to handle it.

The question(s):

It is possible to identify - when in the SendResponse method - the correct Escalation? If yes, how can I do it? If this is not viable, how can I change the way I display the data?

If someone is eager to read the real sources, here is the ASPX code and here is the C# code, but I must warn you: custom classes and properties, methods names and so on are in Italian.

Thanks in advance, Andrea.

+1  A: 

You could use the Command event of the Button and the CommandArgument property as you describe, but create a read-only property on your escalation object that returns some concatenation of the joint primary key. Bind this property to the button's CommandArgument.

If you're not able or don't want to create a read-only property, you could write a simple method in the code-behind to construct the concatenation, and call this from the Eval method, e.g.

<asp:Button ... 
     CommandArgument='<%# ConcatenatePrimaryKeys(Eval("complaint_id"), Eval("escalation_date")) %>'
     runat="server" />
Graham Clark
Well, this seems a perfectly logical solution I completely missed...
kappa