RadGrid client binding get_masterTableView() is null - javascript

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>();
}

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/

Add Dynamic Controls (set of Controls) on Button Click

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.

Looping RadGrid item in clientside

There is a radgrid with one of the column as checkbox in
itemtemplate.
I want to loop through this radgrid's items. And based on each item's checkbox.checked condition, enable a seperate button control.(in client-side using javascript)
I've deviced code for this, but it is not giving the desired output.
What's wrong in this please.
Javascript:
<telerik:RadScriptBlock ID="scriptBlock1" runat="server">
<script type="text/javascript">
function checkRestrictionAcceptance()
{
var masterTable = $find("<%=RGGroupedCartRestrictedAssets.ClientID%>").get_masterTableView();
var count = masterTable.get_dataItems().length;
var checkbox;
var item;
for (var i = 0; i < count; i++)
{
item = masterTable.get_dataItems()[i];
checkbox = item.findElement("AcceptedCheckbox");
alert(checkbox.checked);
if (checkbox.checked)
{
var DownloadButton = document.getElementById('DownloadButton');
DownloadButton.enabled = false;
}
}
}
</script>
</telerik:RadScriptBlock>
Aspx:
<telerik:RadGrid ID="RGGroupedCartRestrictedAssets" runat="server" DataSourceID="CslaDSGroupedCartRestrictedAssets" AutoGenerateColumns="False"
GridLines="None" AllowPaging="True" AllowSorting="True" AllowFilteringByColumn="True" EnableEmbeddedSkins="false">
<MasterTableView DataSourceID="CslaDSGroupedCartRestrictedAssets" DataKeyNames="RestrictionText">
<Columns>
<telerik:GridTemplateColumn>
<ItemTemplate>
<asp:Checkbox ID="AcceptedCheckbox" runat="server" />
</ItemTemplate>
</Columns>
</MasterTableView>
</telerik:RadGrid>
<asp:Button ID="DownloadButton" runat="server" Text = "Test" OnClientClick ="checkRestrictionAcceptance();"/>
You need to specify the clientID of the DownloadButton
var DownloadButton = document.getElementById('<%=DownloadButton.ClientID%>');
I'm not sure which browser you're using, but I think that using the 'i' directly in get_dataItems() can be problematic with Firefox. Your code worked fine for me in IE10 using Telerik.Web.UI 2013.3.1324.45 - I am getting the value of checkbox.checked. Try this instead though, it might help:
function checkRestrictionAcceptance() {
var masterTable = $find("<%=RGGroupedCartRestrictedAssets.ClientID%>").get_masterTableView();
var count = masterTable.get_dataItems().length;
var checkbox;
var items = masterTable.get_dataItems();
for (var i = 0; i < count; i++) {
checkbox = items[i].findElement("AcceptedCheckbox");
alert(checkbox.checked);
if (checkbox.checked) {
var downloadButton = document.getElementById('<%=DownloadButton.ClientID%>');
downloadButton.enabled = false;
}
}

Javascript in Gridview causes other event to fire?

I'm roughly following the concept from this link. To simulate a nested GridView.
It looks like this:
Basically I'm creating a second row which is display:none and want to toggle it using JavaScript.
JavaScript and aspx code:
<script type="text/javascript" language="JavaScript">
function detailsToggle(Company_ID) {
try {
detail_row = document.getElementById('detailsRow_' + Company_ID);
parent_row = document.getElementById('parentRow_' + Company_ID);
img = parent_row.cells[0].firstChild;
if (detail_row.className !== 'hidden') {
detail_row.className = detail_row.className + ' hidden';
img.src = '../Images/icons/+.gif';
}
else {
detail_row.className = detail_row.className.replace(/\bhidden\b/, '');
img.src = '../Images/icons/-.gif';
}
}
catch(ex) { alert(ex); }
}
</script>
<style type="text/css">
.hidden
{
display: none;
}
</style>
<asp:GridView ID="gvLegalEntityBrowser" DataKeyNames="Company_ID" AutoGenerateColumns="False"
runat="server" CellPadding="4" ForeColor="#333333" GridLines="None"
OnRowDataBound="gvLegalEntityBrowser_RowDataBound" OnPageIndexChanging="pagingIndexChanged"
AllowPaging="True" PageSize="25" AllowSorting="false">
<AlternatingRowStyle BackColor="White" ForeColor="#284775" />
<Columns>
<asp:TemplateField>
<ItemTemplate>
<%--Placeholder --%>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="CompanyCode" HeaderText="CompanyCode" SortExpression="CompanyCode" />
<asp:BoundField DataField="CompanyName" HeaderText="CompanyName" SortExpression="CompanyName" />
</Columns>
<EmptyDataTemplate>No data</EmptyDataTemplate>
<EditRowStyle BackColor="#999999" />
<FooterStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" />
<HeaderStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" />
<PagerStyle BackColor="#284775" ForeColor="White" HorizontalAlign="Center" />
<RowStyle BackColor="#F7F6F3" ForeColor="#333333" />
<SelectedRowStyle BackColor="#E2DED6" Font-Bold="True" ForeColor="#333333" />
<SortedAscendingCellStyle BackColor="#E9E7E2" />
<SortedAscendingHeaderStyle BackColor="#506C8C" />
<SortedDescendingCellStyle BackColor="#FFFDF8" />
<SortedDescendingHeaderStyle BackColor="#6F8DAE" />
</asp:GridView>
... and my apsx.cs RowDataBound Method:
//Idea from : http://www.codeproject.com/Articles/160773/Expandable-Rows-in-GridView
protected void gvLegalEntityBrowser_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
GridViewRow gvRow = e.Row as GridViewRow;
Int64 iCompanyID = 0; //Get Company_ID for Legal Entity Row
iCompanyID = System.Convert.ToInt64(gvLegalEntityBrowser.DataKeys[gvRow.RowIndex]["Company_ID"]);
GridView gvLegalEntityRelation = new GridView();
gvRow.ID = "parentRow_" + iCompanyID;
gvRow.ClientIDMode = ClientIDMode.Static; //Set HTML ID element = control.ID
//Add javascript toggle button to each row
System.Web.UI.WebControls.ImageButton toggleButton = new System.Web.UI.WebControls.ImageButton();
toggleButton.ID = "btnToggle_" + iCompanyID;
toggleButton.ImageUrl = "../Images/icons/+.gif";
toggleButton.OnClientClick = "detailsToggle(" + (iCompanyID) + ")";
gvRow.Cells[0].Controls.Add(toggleButton);
toggleButton.Attributes.Add("onmouseover","this.style.cursor='hand'");
toggleButton.Attributes.Add("onmouseout", "this.style.cursor='default'");
using (dsLegalEntitiesTableAdapters.View_LegalEntityRelationCountTableAdapter daLERelCount = new dsLegalEntitiesTableAdapters.View_LegalEntityRelationCountTableAdapter())
{
//Set Details Data Source
gvLegalEntityRelation.DataSource = daLERelCount.GetRelationsDataByCompanyID(iCompanyID);
gvLegalEntityRelation.AutoGenerateColumns = true;
GridViewRow detailsgvRow = new GridViewRow(gvRow.RowIndex + 1, -1, DataControlRowType.EmptyDataRow, DataControlRowState.Normal);
detailsgvRow.CssClass = "hidden";
detailsgvRow.ID = "detailsRow_" + iCompanyID;
detailsgvRow.ClientIDMode = ClientIDMode.Static; //Set HTML ID element = control.ID
TableCell cell = new TableCell();
cell.ColumnSpan = 4;
cell.BorderStyle = BorderStyle.None;
cell.Controls.Add(gvLegalEntityRelation);
detailsgvRow.Cells.Add(cell);
((GridView)sender).Controls[0].Controls.Add(detailsgvRow);
gvLegalEntityRelation.DataBind();
}
}
}
The JavaScript works fine, and I even see the correct Result for a split second:
... but the the parent GridView rebuilds into something like this:
Q: Does anyone have an Idea what may be causing the GridView to rebuild??
So... the problem was actually quite basic. A colleague pointed this out to me.
I used an ImageButton to expand the inner table. The .NET image button has Click handler and ClientClick handler. Click tells what to do on PostBack, and ClientClick passes on to JavaScript.
Apparently, even if I don't define a target function for Click, the page still does a Post-Back. Thus first the javascript works, and then the page does a post-back, messing up the page.
Solution: exchange ImageButton for a simple image with click-event for javascript.

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