Add Dynamic Controls (set of Controls) on Button Click - javascript

I have a requirement to add a panel containing a user control (textbox) + 2 Gridviews with their own item templates + other validations operating on these controls, on a Web-Form dynamically resulting from a button click. So every time a user clicks a button "Add Panel", a new panel would be generated with the above controls.
I am trying the route of Data Lists and repeaters but binding the data to the above controls is becoming a challenge. I would like to investigate other frontiers to achieve this before going forward.
Any help, links, suggestions or pointers would be appreciated?

Just to get you started.
UserControl: DynamicUC.ascx
Page using that user control: DynamicPage.aspx
DyanamicUC.ascx
<div style="float: left">
<asp:TextBox ID="tbMyTextBox" runat="server" />
<asp:GridView runat="server" ID="gvNumbers" AutoGenerateColumns="False">
<Columns>
<asp:BoundField DataField="Serial" HeaderText="Seiral" />
<asp:TemplateField HeaderText="Item Name">
<ItemTemplate>
<%# Eval("Item") %>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</div>
DynamicUC.ascx.cs
public partial class DynamicUC : UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
}
public void PopulateData(string value)
{
tbMyTextBox.Text = value;
gvNumbers.DataSource = Enumerable.Range(1, 5).Select(i => new { Serial = i, Item = "Item " + i });
gvNumbers.DataBind();
}
public string GetData()
{
return Server.HtmlEncode(tbMyTextBox.Text);
}
}
DynamicPage.aspx
<asp:Button ID="btnAddUC" Text="Add UC" runat="server" OnClick="btnAddUC_Click" />
<asp:Button ID="btnGetUCValues" Text="Get UC Values" runat="server" OnClick="btnGetUCValues_Click" />
<asp:Panel runat="server" ID="pnlDynamicUCPanel" Style="overflow: auto;">
</asp:Panel>
<asp:Label ID="lblUCValues" runat="server" Style="clear: both;" />
DynamicPage.aspx.cs
public partial class DynamicPage : System.Web.UI.Page
{
private int NumberOfDynamicControls
{
get
{
var numberOfDynamicControls = ViewState["__dynamicUCCount"];
if (numberOfDynamicControls != null)
{
return (int)numberOfDynamicControls;
}
return 0;
}
set
{
ViewState["__dynamicUCCount"] = value;
}
}
private List<DynamicUC> _dynamicUCList;
protected void Page_Load(object sender, EventArgs e)
{
RestoreDynamicUC();
}
protected void btnAddUC_Click(object sender, EventArgs e)
{
CreateDyanamicUC(NumberOfDynamicControls);
NumberOfDynamicControls++;
}
private void RestoreDynamicUC()
{
if (NumberOfDynamicControls == 0)
return;
for (int i = 0; i < NumberOfDynamicControls; i++)
{
CreateDyanamicUC(i);
}
}
private void CreateDyanamicUC(int dataIndex)
{
if (_dynamicUCList == null)
{
_dynamicUCList = new List<DynamicUC>();
}
var dynamicUC = LoadControl("DynamicUC.ascx") as DynamicUC;
dynamicUC.PopulateData("Data " + dataIndex);
pnlDynamicUCPanel.Controls.Add(dynamicUC);
_dynamicUCList.Add(dynamicUC);
}
protected void btnGetUCValues_Click(object sender, EventArgs e)
{
var valuesText = "";
if (_dynamicUCList != null)
{
valuesText = string.Join(", ", _dynamicUCList.Select(duc => duc.GetData()));
}
lblUCValues.Text = "UC Values: " + valuesText;
}
}
There is a lot to explain; but I am afraid I have little time. But this should give some hint.

Related

Create gridview C# asp.net with Collapsable/Expandable Rows

this is a table in my database. I want to create a Gridview with collapsable and expandable rows.
StartDate EndDate Section_Name Section_Value
2017-06-27 2017-06-28 Section 1 pump1 300
2017-06-27 2017-06-28 Section 1 pump2 256
2017-06-27 2017-06-28 Section 1 pump3 11
2017-06-27 2017-06-28 Section 1 pump4 5252
2017-06-27 2017-06-28 Section 2 pump1 300
2017-06-27 2017-06-28 Section 2 pump2 256
2017-06-27 2017-06-28 Section 2 pump3 212
2017-06-27 2017-06-28 Section 3 pump1 1222
How I want it to look in the gridview:
(+-) SECTION 1 TOTAL: 5819
Section 1 pump1 300
Section 1 pump2 256
Section 1 pump3 11
Section 1 pump4 5252
(+-) SECTION 2 TOTAL: 786
Section 2 pump1 300
Section 2 pump2 256
Section 2 pump3 212 and so on...
If you click on SECTION 1 it should display all that falls under section 1 and so forth.
The code (javascript):
<script language="javascript" type="text/javascript">
$(document).ready(function () {
$('.ExpandCollapseStyle').click(function () {
var orderId = $(this).attr('alt');
if (!isDisplayed($('.ExpandCollapse' + orderId))) {
$(this).attr('src', 'images/minus.gif');
$('.ExpandCollapse' + orderId).css("display", "block");
}
else {
$(this).attr('src', 'images/plus.gif');
$('.ExpandCollapse' + orderId).css("display", "none");
}
})
$('.ExpandCollapseGrandStyle').click(function () {
$(".grdViewOrders tr").each(function () {
var orderId = $(this).find(".ExpandCollapseStyle").attr('alt');
if (orderId != 'undefined') {
if ($(this).attr('alt') == 'Expanded') {
$(this).find(".ExpandCollapseStyle").attr('src', 'images/minus.gif');
$('.ExpandCollapse' + orderId).css("display", "block");
$(this).attr('alt', 'Collapsed');
}
else {
$(this).find(".ExpandCollapseStyle").attr('src', 'images/plus.gif');
$('.ExpandCollapse' + orderId).css("display", "none");
$(this).attr('alt', 'Expanded');
}
}
});
if ($('.ExpandCollapseGrandStyle').attr('alt') == 'Expanded') {
$('.ExpandCollapseGrandStyle').attr('src', 'images/plus.gif');
$('.ExpandCollapseGrandStyle').attr('alt', 'Collapsed');
}
else {
$('.ExpandCollapseGrandStyle').attr('src', 'images/minus.gif');
$('.ExpandCollapseGrandStyle').attr('alt', 'Expanded');
}
})
function isDisplayed(object) {
// if the object is visible return true
if ($(object).css('display') == 'block') {
return true;
}
// if the object is not visible return false
return false;
};
});
</script>
(Gridview)
<asp:GridView ID="grdViewOrders" BackColor="WhiteSmoke" runat="server" AutoGenerateColumns="False" CssClass="grdViewOrders"
GridLines="Vertical" ShowFooter="True" OnRowDataBound="grdViewOrders_RowDataBound"
onrowcreated="grdViewOrders_RowCreated" >
<Columns>
<asp:TemplateField HeaderText="Section Name" >
<ItemStyle Width="10px" />
<ItemTemplate>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Section Value">
<ItemStyle Width="10px" />
<ItemTemplate>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField HeaderText="" DataField="Section_Name">
<HeaderStyle Width="150px" />
<ItemStyle Width="150px" />
</asp:BoundField>
<asp:BoundField HeaderText="" DataField="Section_Value">
<HeaderStyle Width="150px" />
<ItemStyle Width="150px" />
</asp:BoundField>
</Columns>
<HeaderStyle Height="25px" Font-Bold="True" BackColor="DimGray" ForeColor="White"
HorizontalAlign="Center" VerticalAlign="Middle" />
<RowStyle Height="25px" BackColor="Gainsboro" HorizontalAlign="Center" VerticalAlign="Middle" />
<AlternatingRowStyle Height="25px" BackColor="LightGray" HorizontalAlign="Center"
VerticalAlign="Middle" />
<FooterStyle BackColor="Gray" />
</asp:GridView>
(Code Behind C#)
public partial class Default3 : System.Web.UI.Page
{
// To keep track of the previous row Group Identifier
string strPreviousRowID = string.Empty;
// To keep track the Index of Group Total
int intSectionTotalIndex = 1;
string strGroupHeaderText = string.Empty;
double dblSectionTotal = 0;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
Method();
}
}
protected void Method()
{
connection made to sql db and bind data to gv
}
protected void grdViewOrders_RowCreated(object sender, GridViewRowEventArgs e)
{
bool IsSectionTotalRowNeedtoAdd = false;
if ((strPreviousRowID != string.Empty) && (DataBinder.Eval(e.Row.DataItem, "Section_Name") == null))
{
IsSectionTotalRowNeedtoAdd = true;
intSectionTotalIndex = 0;
}
if (IsSectionTotalRowNeedtoAdd)
{
#region SectionTotal
GridView grdViewOrders = (GridView)sender;
// Creating a Row
GridViewRow row = new GridViewRow(0, 0, DataControlRowType.DataRow, DataControlRowState.Insert);
//Adding Group Expand Collapse Cell
TableCell cell = new TableCell();
System.Web.UI.HtmlControls.HtmlImage img = new System.Web.UI.HtmlControls.HtmlImage();
img.Src = "images/minus.gif";
img.Attributes.Add("class", "ExpandCollapseGrandStyle");
img.Attributes.Add("alt", "Expanded");
cell.Controls.Add(img);
cell.HorizontalAlign = HorizontalAlign.Left;
row.Cells.Add(cell);
//Adding Expand Collapse Cell
cell = new TableCell();
row.Cells.Add(cell);
//Adding Header Cell
cell = new TableCell();
cell.Text = "Section 1 Total";
cell.HorizontalAlign = HorizontalAlign.Left;
cell.ColumnSpan = 1;
row.Cells.Add(cell);
//Adding Amount Column
cell = new TableCell();
cell.HorizontalAlign = HorizontalAlign.Right;
row.Cells.Add(cell);
//Adding the Row at the RowIndex position in the Grid
grdViewOrders.Controls[0].Controls.AddAt(e.Row.RowIndex, row);
#endregion
}
}
protected void grdViewOrders_RowDataBound(object sender, GridViewRowEventArgs e)
{ if (e.Row.RowType == DataControlRowType.DataRow)
{
strPreviousRowID = DataBinder.Eval(e.Row.DataItem, "Section_Name").ToString();
double dblSAmount = Convert.ToDouble(DataBinder.Eval(e.Row.DataItem, "Section_Value").ToString());
dblSectionTotal += dblSAmount;
e.Row.Style.Add("display", "block");
e.Row.CssClass = "ExpandCollapse" + strPreviousRowID;
}
}
If there is an easier way to do this, please leave a link or some tips. Thank you.
For further reference I was trying to make use of the source:
http://www.dotnettwitter.com/2012/07/group-total-and-grand-total-in-gridview_15.html
Try this example:
ASPX Code:
<asp:GridView ID="gvCustomers" runat="server" AutoGenerateColumns="false" CssClass="Grid"
DataKeyNames="CustomerID" OnRowDataBound="OnRowDataBound">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<img alt = "" style="cursor: pointer" src="images/plus.png" />
<asp:Panel ID="pnlOrders" runat="server" Style="display: none">
<asp:GridView ID="gvOrders" runat="server" AutoGenerateColumns="false" CssClass = "ChildGrid">
<Columns>
<asp:BoundField ItemStyle-Width="150px" DataField="OrderId" HeaderText="Order Id" />
<asp:BoundField ItemStyle-Width="150px" DataField="OrderDate" HeaderText="Date" />
</Columns>
</asp:GridView>
</asp:Panel>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField ItemStyle-Width="150px" DataField="ContactName" HeaderText="Contact Name" />
<asp:BoundField ItemStyle-Width="150px" DataField="City" HeaderText="City" />
</Columns>
.CS Code
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
gvCustomers.DataSource = GetData("select top 10 * from Customers");
gvCustomers.DataBind();
}
}
private static DataTable GetData(string query)
{
string strConnString = ConfigurationManager.ConnectionStrings["constr"].ConnectionString;
using (SqlConnection con = new SqlConnection(strConnString))
{
using (SqlCommand cmd = new SqlCommand())
{
cmd.CommandText = query;
using (SqlDataAdapter sda = new SqlDataAdapter())
{
cmd.Connection = con;
sda.SelectCommand = cmd;
using (DataSet ds = new DataSet())
{
DataTable dt = new DataTable();
sda.Fill(dt);
return dt;
}
}
}
}
}
protected void OnRowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
string customerId = gvCustomers.DataKeys[e.Row.RowIndex].Value.ToString();
GridView gvOrders = e.Row.FindControl("gvOrders") as GridView;
gvOrders.DataSource = GetData(string.Format("select top 3 * from Orders where CustomerId='{0}'", customerId));
gvOrders.DataBind();
}
}
Client side Expand Collapse functionality using jQuery and JavaScript
For Expand and Collapse of the Child GridViews I have made use of jQuery
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script type="text/javascript">
$("[src*=plus]").live("click", function () {
$(this).closest("tr").after("<tr><td></td><td colspan = '999'>" + $(this).next().html() + "</td></tr>")
$(this).attr("src", "images/minus.png");
});
$("[src*=minus]").live("click", function () {
$(this).attr("src", "images/plus.png");
$(this).closest("tr").next().remove();
});
Link 1: https://www.aspsnippets.com/Articles/Nested-GridView-Example-in-ASPNet-using-C-and-VBNet.aspx
Link 2: http://www.c-sharpcorner.com/UploadFile/b926a6/nested-grid-view-in-Asp-Net/

Hide a server side control from custom control's code behind file in c#

I have a server side div tag in my za.aspx page which contains a label and dropdownlist
<div id="SkillsStatus" runat="server" style="display:none">
<asp:Label ID="Label1" runat="server" Text="Please select a skill"
Font-Bold="True" Font-Italic="False" Font-Size="Larger"></asp:Label>
<asp:DropDownList ID="SkillsStatusddl" runat="server" AutoPostBack="True"
onselectedindexchanged="SkillsStatusddl_SelectedIndexChanged"
CssClass="selectpicker">
<asp:ListItem Value="0">Choose An Option</asp:ListItem>
</asp:DropDownList>
now, i am binding data to dropdownlist at codebehind file, with that i am binding a cusom control in code behind file
PreChatSurvey customPrechatSurvey = new PreChatSurvey
{
ID = "customPrechatSurvey",
ForeColor = Color.Black,
SurveyId = 0,
IsPreview = false
};
protected override void OnInit(EventArgs e)
{
SkillsStatus.Attributes.Add("style", "display:block");
SkillsStatusddl.DataSource = "";
orgID = Convert.ToInt32(Request.QueryString["OrgID"]);
DataSet ds = SubCampaignBase.GetSkillStatus(orgID);
DataTable dt = ds.Tables[0];
foreach (DataRow row in dt.Rows)
{
ListItem li = new ListItem();
li.Text = row["SubCampaignName"].ToString();
li.Value = row["SubCampaignId"].ToString();
li.Attributes.Add("data-icon", "glyphicon glyphicon-user");
if (Convert.ToBoolean(row["soa_status"]))
{
li.Attributes.CssStyle.Add(HtmlTextWriterStyle.Color, "green");
li.Attributes.CssStyle.Add(HtmlTextWriterStyle.BackgroundColor, "white");
}
else
{
li.Attributes.CssStyle.Add(HtmlTextWriterStyle.Color, "black");
li.Attributes.CssStyle.Add(HtmlTextWriterStyle.BackgroundColor, "white");
}
SkillsStatusddl.Items.Add(li);
}
base.OnInit(e);
}
now it loads a custom control and dropdown on same page, this custom control have a button, and on that button click, i want to hide the div tag containing the dropdown so i write following on button click
private void btnSubmit_Click(object sender, EventArgs e)
{
DropDownList dd = (DropDownList)this.Parent.FindControl("SkillsStatusddl");
dd.Enabled = false;
HtmlGenericControl div = (HtmlGenericControl)this.Parent.FindControl("SkillsStatus");
div.Attributes.Add("style", "display:none");
}
For safety, i have tried two things,
But nothing is working, neither the div gets disappear nor dropdown gets disabled

Find Button inside a Gridview and click it from codebehind(c#)

I need to click a button that is inside a gridview from the codebehind. I think the best approach will be to create a javascript function in codebehind, something like the second solution i tried below. I will appreciate any help
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "Accepted")
{
int index = Convert.ToInt32(e.CommandArgument);
GridViewRow row = GridView1.Rows[index];
//find button
Button btnEsc = (Button)row.FindControl("btnEsc");
//here I would like to simulate a click on this button, so far no luck
btnEsc.Click(); // this is wrong
}
}
I also try this but it doesn't find the button: I dont know how to find the button inside the gridview
System.Text.StringBuilder sbScript = new System.Text.StringBuilder("");
sbScript.Append("document.getElementById('btnEsc').click();");
ScriptManager.RegisterStartupScript(this, GetType(), "ClientScript", sbScript.ToString(), true);
When you open the lightbox, pass in the Id to a hidden Field. You can then read it out later. Example from ListView here.
protected void lvProjectServices_ItemCreated(object sender, ListViewItemEventArgs e)
{
if (e.Item.DataItem != null)
{
Whatever data = (Whatever)e.Item.DataItem;
PlaceHolder objPlc3 = (PlaceHolder)e.Item.FindControl("phEdit");
LinkButton link3 = new LinkButton();
link3.Text = "<i class=\"table-edit\"></i>";
link3.ID = "lbEditServer" + data.Id.ToString();
link3.CommandName = "Edit";
link3.CommandArgument = data.Id.ToString();
link3.Click += link_Click;
objPlc3.Controls.Add(link3);
}
}
void link_Click(object sender, EventArgs e)
{
LinkButton btn = (LinkButton)sender;
int Id = int.Parse(btn.CommandArgument.ToString());
txtProjectServiceId.Value = Id.ToString();
ScriptManager scriptManager = ScriptManager.GetCurrent(Page);
if (!scriptManager.IsClientScriptBlockRegistered("openSvcModal"))
{
ScriptManager.RegisterStartupScript(Page, Page.GetType(), "openSvcModal", "$('select').select2(); $('#editProjectService').modal();", true);
}
}
Code behind:
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
btn.Text = "Refreshed";
if (Request.Params["btnPressed"] != null && Request.Params["btnPressed"] == "true")
{
ScriptManager.RegisterStartupScript(Page, typeof(Page), "OpenWindow", string.Format("$('#{0}').click()", btn.ClientID), true);
}
}
protected void btn_Click(object sender, EventArgs e)
{
btn.Text = "Not Refreshed";
lbl.Text = "Not Refreshed";
System.Threading.Thread.Sleep(1000);
////to refresh the page
Page.Response.Redirect(HttpContext.Current.Request.Url.ToString()+"?btnPressed=true", true);
}
}
Load jquery in aspx page:
<body>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<form id="form1" runat="server">
<div>
<asp:Button runat="server" ID="btn" OnClick="btn_Click" PostBackUrl="/WebForm1.aspx" />
<asp:Label runat="server" ID="lbl"> </asp:Label>
</div>
</form>
</body>
You should really learn jquery, its a great tool. g/l.

RadGrid client binding get_masterTableView() is null

I am setting the datasource at the client side but the get_masterTableView returns null
var tableView = radGrid
.get_masterTableView();
i tried it setting on button click just to be sure that the Radgrid is completely created but it still returns null.. This is my code
<h4>Client Side Binding</h4>
<telerik:RadButton
ID="RadButton1"
AutoPostBack="False"
OnClientClicked="RadButton1_OnClientClicked"
runat="server"
Text="Load Items"></telerik:RadButton>
<telerik:RadGrid
ID="RadGrid1"
AutoGenerateColumns="False"
runat="server">
<MasterTableView>
<Columns>
<telerik:GridBoundColumn
DataField="Name"
HeaderText="Name">
</telerik:GridBoundColumn>
<telerik:GridBoundColumn
DataField="Age"
HeaderText="Age">
</telerik:GridBoundColumn>
<telerik:GridBoundColumn
DataField="Address.City"
HeaderText="City">
</telerik:GridBoundColumn>
</Columns>
</MasterTableView>
<ClientSettings>
<ClientEvents OnGridCreated="RadGrid1_OnGridCreated" />
</ClientSettings>
</telerik:RadGrid>
and this is on the Javascript
<telerik:RadScriptBlock runat="server">
<script>
function pageLoad(sender, args) {
//rebindGrid();
}
function RadButton1_OnClientClicked(sender, args) {
rebindGrid();
}
function RadGrid1_OnGridCreated(sender, args) {
//rebindGrid();
}
function rebindGrid() {
var ds = dataSource();
var radGrid = $find('<%= RadGrid1.ClientID %>');
var tableView = radGrid
.get_masterTableView();
console.log(radGrid);
if (tableView) {
tableView.set_dataSource(ds);
tableView.dataBind();
tableView.set_virtualItemCount(2);
} else {
alert('Table View is null');
}
}
function dataSource() {
var items = [];
items.push({
Name: 'Enteng',
Age: 25,
Address: {
City: 'Dipolog City'
}
});
items.push({
Name: 'Vincent',
Age: 27,
Address: {
City: 'Dumaguete City'
}
});
return items;
}
</script>
</telerik:RadScriptBlock>
pageLoad doesn't work
RadButton1_OnClientClicked doesn't work
RadGrid1_OnGridCreated doesn't work
any help would be appreciated..
TYI
OnGridCreated should work. I think there is a bug in your code:
This:
var radGrid = $find('<%= RadGrid1.ClientID %>');
should look like:
var radGrid = $find('#<%= RadGrid1.ClientID %>');
Alternatively you can use the sender argument to get a handle on your radgrid:
function RadGrid1_OnGridCreated(sender, args) {
rebindGrid(sender);
}
function rebindGrid(sender) {
var tableView = sender.get_masterTableView();
... etc
EDIT:
As stated in the comment below the problem is that the radgird is not bound to any data
source. Thus get_masterTableView() returns null.
The following piece of code, that binds the grid to a dummy data source, solves the problem:
protected void Page_Load(object sender, EventArgs e)
{
RadGrid1.DataSource = new List<int>();
}

How to add new row to repeater without losing information in checkboxes

I have a simple Repeater that contains a checkbox and a Full name per each row.
In addition, I have an "Add Name" button that adds a new full name to the database.
Supposingly user checks a few checkboxes and decides to add another name, I would like to be able to add a new name to the repeater without losing the information in the checkboxes that have been already checked.
I understand some javascript code might do the trick the question is how to approach it?
What do I do?
thanks in advance
p.s.
I'll be glad to hear any advice, not olny regarding js.
Here is quick solution, not very pretty but get the job done. Hope it will give you some new ideas
Default.aspx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace RepeaterCheckbox
{
public partial class _Default : System.Web.UI.Page
{
[Serializable]
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
List<Person> personsFromDatabase
{
get { return (List<Person>)ViewState["persons"]; }
set { ViewState["persons"] = value; }
}
//here we will store our person selection state
Dictionary<int,bool> personSelectionState
{
get { return (Dictionary<int, bool>)ViewState["data"]; }
set { ViewState["data"] = value; }
}
protected override void OnLoad(EventArgs e)
{
if (!IsPostBack)
{
#region Test data
personsFromDatabase = new List<Person>{
new Person { Id = 1, Name = "Paul", },
new Person { Id = 2, Name = "Tom", },
};
#endregion
Bind(false);
}
base.OnLoad(e);
}
void Bind(bool isPostback)
{
if (!isPostback)
{
//initialize person selection mapping
personSelectionState = new Dictionary<int, bool>();
foreach (Person person in personsFromDatabase)
personSelectionState.Add(person.Id, false);
}
//map persons to anonymous type that will help us define necessary values
rpPersons.DataSource = personsFromDatabase.Select(x => new
{
Id = x.Id,
Name = x.Name,
//get stored selection state for person
Selected = personSelectionState[x.Id],
});
rpPersons.DataBind();
}
protected void btnAddPerson_Click(object sender, EventArgs e)
{
//update selection states
UpdateSelectionStatuses();
if (!String.IsNullOrEmpty(txbName.Text))
{
//add new person
personsFromDatabase.Add(new Person
{
Id = personsFromDatabase.Count +1,
Name = txbName.Text,
});
//add status mapping for new person so there is no error on postback binding
personSelectionState.Add(personsFromDatabase.Count, false);
//Refresh data on page, to see new person
Bind(true);
}
}
void UpdateSelectionStatuses()
{
//loop through all items
for (int i = 0; i < rpPersons.Items.Count; ++i)
{
RepeaterItem repeaterItem = rpPersons.Items[i];
//find checkbox for item
var checkbox = (CheckBox)repeaterItem.FindControl("chbSelected");
if (checkbox != null)
{
//get our custom attribute
int id = int.Parse(checkbox.Attributes["personId"]);
//update stored checkbox status
personSelectionState[id] = checkbox.Checked;
}
}
}
protected void rpPersons_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
var item = e.Item.DataItem;
var checkbox = (CheckBox)e.Item.FindControl("chbSelected");
if (item != null && checkbox != null)
{
//get person id from our helper anonymous type
System.Reflection.PropertyInfo[] anonymousTypeProperties = item.GetType().GetProperties();
int id = (int)anonymousTypeProperties.Where(x => x.Name == "Id").FirstOrDefault().GetValue(item, null);
//set custom attribute on checkbox to map checkbox with person
checkbox.Attributes["personId"] = id.ToString();
}
}
}
}
}
Default.aspx
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="RepeaterCheckbox._Default" %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Repeater runat="server" ID="rpPersons" OnItemDataBound="rpPersons_ItemDataBound" >
<ItemTemplate>
<p>
<asp:CheckBox ID="chbSelected" runat="server" AutoPostBack="false" Checked='<%# DataBinder.Eval(Container.DataItem, "Selected") %>' />
<asp:Label ID="lblName" runat="server" Text='<%# DataBinder.Eval(Container.DataItem, "Name") %>' />
</p>
</ItemTemplate>
</asp:Repeater>
<div>
<asp:TextBox ID="txbName" runat="server" />
<asp:Button ID="btnAddPerson" runat="server" Text="Add person" OnClick="btnAddPerson_Click" />
</div>
</div>
</form>
</body>
</html>
It depends how do you approach it. Are you using the asp.net repeater in an Ajax update panel?
If is the case you can save check box value at each click event this way when you add a new item the control will be rebinded with the updated values.
If you like to use client side javascript thie post could help you:
How to add rows to a repeater in client side

Categories

Resources