Reputation: 1194
I would like to send a Guid which should be associated with each radio button as eventargs when the user clicks checkout. I was able to achieve this functionality with just a RadioButtonList but I cannot use that here as the rest of the fields are pulled from the database.
There are numerous questions dealing with this type of topic but I could not find one that addresses exactly what I am trying to achieve.
I have the below list
<asp:Content ID="SubscriptionContent" ContentPlaceHolderID="MainContent" ViewStateMode="Enabled" runat="server">
<asp:Panel ID="SubscriptionPanel" CssClass="shopping-cart" ViewStateMode="Enabled" runat="server">
<asp:ListView ID="NewSubscription" runat="server">
<LayoutTemplate>
<table class="table">
<thead>
<th>Select a Subscription</th>
<th>Subscription Level
</th>
<th>Description
</th>
<th>Price
</th>
</thead>
<tbody>
<tr id="itemPlaceholder" runat="server" />
</tbody>
</table>
</LayoutTemplate>
<ItemTemplate>
<tr>
<td class="description"><asp:RadioButton ID="SubscriptionLevel" GroupName="SubscriptionRadio" Text='<%# Eval("SubscriptionLevel") %>' runat="server" /></td>
<td class="description"><asp:Label ID="Details" Text='<%# Eval("Details") %>' runat="server"></asp:Label></td>
<td class="price"><asp:Label runat="server" Text='<%# Eval("Price", "{0:C2}") %>'></asp:Label></td>
<asp:TextBox ID="Id" runat="server" Visible="false" Text='<%# Eval("Id") %>' />
</tr>
</ItemTemplate>
</asp:ListView>
<asp:Button ID="Subscribe" CssClass="btn btn-primary" runat="server" Text="<%$ Snippet: Ecommerce/ShoppingCart/CheckoutButtonLabel, Checkout %>" OnClick="BuySubscription" />
<script type="text/javascript">
$(document).ready(function () {
$("input:radio").attr('name', 'SubscriptionRadio');//Override the naming that asp does
});
</script>
</asp:Panel>
</asp:Content>
I am thinking that if I could update a hidden field with the corresponding guid value for each radio button and submit that when the user triggers BuySubscription
. I am not sure how to do this though. Ultimately I just want the user to be able to select one of the subscription options and pass that guid back to the function.
Thank you in advance for any input.
Upvotes: 1
Views: 3273
Reputation: 31198
The first problem you're going to run into is that ASP.NET gives each <input type="radio" />
a different name, because it's in a different NamingContainer
.
You've added some script to try to work around that by changing the name attribute on the client. Unfortunately, this won't work. When you post the form back to the server, ASP.NET will still be looking for a value using the generated name, which won't exist.
The quick and dirty solution would be to update your script to copy the value from the hidden TextBox
to the value attribute of the radiobutton. You would then have to use Request.Form["SubscriptionRadio"]
to retrieve the value of the selected option:
<ItemTemplate>
<tr>
<td class="description">
<asp:RadioButton ID="SubscriptionLevel" runat="server"
GroupName="SubscriptionRadio"
Text='<%# Eval("SubscriptionLevel") %>'
/>
<%-- NB: Can't set Visible="False", otherwise it's not rendered: --%>
<asp:TextBox ID="Id" runat="server"
Style="display:none;"
Text='<%# Eval("Id") %>'
/>
</td>
...
</tr>
</ItemTemplate>
...
<script>
$(document).ready(function() {
$("input:radio").each(function(){
var me = $(this);
var id = me.closest("tr").find("input[name$=Id]").val();
me.attr("value", id);
me.attr('name', 'SubscriptionRadio');
});
});
</script>
Alternatively, you could use a custom RadioButton
control which works within a data-bound control. I posted a simple example back in 2012: https://stackoverflow.com/a/13271444/124386
using System;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Reflection;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace SiteControls
{
[ToolboxData("<{0}:ListRadioButton runat=\"server\" />")]
public class ListRadioButton : RadioButton
{
private static readonly FieldInfo UniqueGroupNameField = FindUniqueGroupNameField();
private string _uniqueGroupName;
private static FieldInfo FindUniqueGroupNameField()
{
return typeof(RadioButton).GetField("_uniqueGroupName",
BindingFlags.NonPublic | BindingFlags.Instance);
}
public string Value
{
get { return Attributes["value"]; }
set { Attributes["value"] = value; }
}
protected virtual string CreateUniqueGroupName()
{
string result = GroupName;
if (string.IsNullOrEmpty(result))
{
result = ID;
}
if (string.IsNullOrEmpty(result))
{
result = UniqueID;
}
else
{
Control container = NamingContainer;
if (container != null)
{
if (container is IDataItemContainer)
{
container = container.NamingContainer ?? container;
}
result = container.UniqueID + base.IdSeparator + result;
}
else
{
string uniqueID = UniqueID;
if (!string.IsNullOrEmpty(uniqueID))
{
int index = uniqueID.LastIndexOf(base.IdSeparator);
if (index != -1)
{
result = uniqueID.Substring(0, 1 + index) + result;
}
}
}
}
return result;
}
private void EnsureUniqueGroupName()
{
if (_uniqueGroupName == null)
{
string value = CreateUniqueGroupName();
if (UniqueGroupNameField != null) UniqueGroupNameField.SetValue(this, value);
_uniqueGroupName = value;
value = base.Attributes["value"];
if (string.IsNullOrEmpty(value))
{
base.Attributes["value"] = UniqueID;
}
}
}
protected override bool LoadPostData(string postDataKey, NameValueCollection postCollection)
{
EnsureUniqueGroupName();
return base.LoadPostData(postDataKey, postCollection);
}
protected override void Render(HtmlTextWriter writer)
{
EnsureUniqueGroupName();
base.Render(writer);
}
}
}
You can either register the control in the page markup:
<%@ Register tagPrefix="site" namespace="SiteControls" %>
or in the web.config
file:
<?xml version="1.0"?>
<configuration>
<system.web>
<pages>
<controls>
<add
tagPrefix="site"
namespace="SiteControls"
/>
</controls>
</pages>
</system.web>
</configuration>
With that in place, you can lose the script and the hidden TextBox
:
<ItemTemplate>
<tr>
<td class="description"><site:ListRadioButton ID="SubscriptionLevel" runat="server"
GroupName="SubscriptionRadio"
Text='<%# Eval("SubscriptionLevel") %>'
Value='<%# Eval("Id") %>'
/></td>
...
To find the selected item, you would then need to loop through the ListView
's Items
, find the RadioButton
control, and look at the Checked
property:
ListRadioButton selectedItem = NewSubscription.Items
.Select(item => (ListRadioButton)item.FindControl("SubscriptionLevel"))
.FirstOrDefault(radio => radio != null && radio.Checked);
string selectedValue = (selectedItem == null) ? null : selectedItem.Value;
Upvotes: 2