I hope to explain my problem clearly.
I have a asp.net page (default.aspx) with a ScriptManager, an UpdatePanel containing a PlaceHolder (PlaceHolderUC) and two buttons (btnAddControl and btnRefreshPage) triggered to this UpdatePanel.
I have a Web User Control (UControl.ascx) with a table containing some html controls:
a textbox (txtOrder) where I store the order number of the control itself; it is useful for me to understand if the sorting works; then it will be replaced by a hidden control
a label (lblTest) where I write the name of the control (eg. Control #1)
a textbox (txtTest) where, when i run the project, I write some text to test persistence of the controls
a button (btnMoveDown) to move the control downwards
a button (btnMoveUp) to move the control upwards
a button (btnRemove) to remove the control
When I press button "btnAddControl", add a new UControl to the placeholder "PlaceHolderUC";
Everything works fine; even removing the control, when I press the "btnRemove" button, works.
Page after adding 4 UControl
The problem occurs when I want to move the controls by pressing the "btnMoveDown" and "btnMoveUp" buttons.
The logical move works, but the panel is not updated.
I pressed the "btnMoveDown" button on Control # 2; it updated the sort textbox (txtOrder) field but did not physically move the controls
To update the panel I have to press the "btnRefreshPage" button.
I tried adding the UPanel.Update(); command after the button is pressed, but that doesn't work either.
The list "UControlList" is used to keep data persistence.
I also tried moving component loading from Page_Load to other page events, but it still doesn't work
This is my code.
default.aspx
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="default.aspx.cs" Inherits="TestUpdatePanel._default" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Test Update Panel</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<p>
<asp:Button ID="btnAddControl" runat="server" Text="Add control" OnClick="btnAddControl_Click" />
</p>
<asp:ScriptManager ID="SManager" runat="server"></asp:ScriptManager>
<asp:UpdatePanel ID="UPanel" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:PlaceHolder ID="PlaceHolderUC" runat="server"></asp:PlaceHolder>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="btnAddControl" EventName="Click" />
<asp:AsyncPostBackTrigger ControlID="btnRefreshPage" EventName="Click" />
</Triggers>
</asp:UpdatePanel>
<asp:Button ID="btnRefreshPage" runat="server" Text="Refresh Page" OnClick="btnRefreshPage_Click" />
</div>
</form>
</body>
</html>
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 TestUpdatePanel
{
[Serializable]
public class UControlClass
{
public UControlClass()
{
}
public int ID { get; set; }
public int Order { get; set; }
public String Label { get; set; }
}
public partial class _default : System.Web.UI.Page
{
public List<UControlClass> UControlList
{
get
{
if (ViewState["UControlList"] == null)
ViewState["UControlList"] = new List<UControlClass>();
return (List<UControlClass>)ViewState["UControlList"];
}
set
{
ViewState["UControlList"] = value;
}
}
private void ReloadControls()
{
int i = 0;
foreach (var tmp in UControlList.OrderBy(x => x.Order))
{
i++;
var c = (UControl)LoadControl("UControl.ascx");
c.ID = "C_" + tmp.ID.ToString();
c.Label = tmp.Label;
c.IsFirst = (i == 1);
c.IsLast = (i == UControlList.Count);
c.BtnRemoveClickEvent += C_BtnRemoveClickEvent;
c.BtnMoveUpClickEvent += C_BtnMoveUpClickEvent;
c.BtnMoveDownClickEvent += C_BtnMoveDownClickEvent;
PlaceHolderUC.Controls.Add(c);
}
}
protected void Page_Load(object sender, EventArgs e)
{
ReloadControls();
}
private void RefreshSorting()
{
int i = 0;
foreach (var tmp in UControlList.OrderBy(x => x.Order))
{
i++;
var c = (UControl)PlaceHolderUC.FindControl("C_" + tmp.ID.ToString());
if (c == null)
return;
c.IsFirst = (i == 1);
c.IsLast = (i == UControlList.Count);
}
}
protected void btnAddControl_Click(object sender, EventArgs e)
{
UControlClass UClass = new UControlClass();
UClass.ID = UControlList.DefaultIfEmpty().Max(x => x == null ? 0 : x.ID) + 1;
UClass.Order = UControlList.DefaultIfEmpty().Max(x => x == null ? 0 : x.Order) + 1;
UClass.Label = "Control # " + UClass.ID.ToString();
var c = (UControl)LoadControl("UControl.ascx");
c.ID = "C_" + UClass.ID.ToString();
c.Order = UClass.Order;
c.Label = UClass.Label;
c.BtnRemoveClickEvent += C_BtnRemoveClickEvent;
c.BtnMoveUpClickEvent += C_BtnMoveUpClickEvent;
c.BtnMoveDownClickEvent += C_BtnMoveDownClickEvent;
c.IsFirst = (UControlList.Count == 0);
c.IsLast = true;
UControlList.Add(UClass);
PlaceHolderUC.Controls.Add(c);
RefreshSorting();
}
private void C_BtnMoveDownClickEvent(object sender, UControlEventArgs e)
{
try
{
var CurrentControl = (UControl)PlaceHolderUC.FindControl("C_" + e.ID.ToString());
var CurrentList = UControlList.Find(x => x.ID == e.ID);
if (CurrentControl == null || CurrentList == null || CurrentControl.Order != CurrentList.Order)
return;
var NextList = UControlList.OrderBy(x => x.Order).Reverse().TakeWhile(x => x.Order > CurrentControl.Order).LastOrDefault();
if (NextList == null)
return;
var NextControl = (UControl)PlaceHolderUC.FindControl("C_" + NextList.ID.ToString());
if (NextControl == null || NextControl.Order != NextList.Order)
return;
Int32 tmp = CurrentControl.Order;
CurrentControl.Order = NextControl.Order;
CurrentList.Order = NextControl.Order;
NextControl.Order = tmp;
NextList.Order = tmp;
RefreshSorting();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
private void C_BtnMoveUpClickEvent(object sender, UControlEventArgs e)
{
try
{
var CurrentControl = (UControl)PlaceHolderUC.FindControl("C_" + e.ID.ToString());
var CurrentList = UControlList.Find(x => x.ID == e.ID);
if (CurrentControl == null || CurrentList == null || CurrentControl.Order != CurrentList.Order)
return;
var PreviousList = UControlList.OrderBy(x => x.Order).TakeWhile(x => x.Order < CurrentControl.Order).LastOrDefault();
if (PreviousList == null)
return;
var PreviousControl = (UControl)PlaceHolderUC.FindControl("C_" + PreviousList.ID.ToString());
if (PreviousControl == null || PreviousControl.Order != PreviousList.Order)
return;
Int32 tmp = CurrentControl.Order;
CurrentControl.Order = PreviousControl.Order;
CurrentList.Order = PreviousControl.Order;
PreviousControl.Order = tmp;
PreviousList.Order = tmp;
RefreshSorting();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
private void C_BtnRemoveClickEvent(object sender, UControlEventArgs e)
{
try
{
var c = (UControl)PlaceHolderUC.FindControl("C_" + e.ID.ToString());
if (c == null)
return;
UControlList.RemoveAll(x => x.ID == e.ID);
PlaceHolderUC.Controls.Remove(c);
c.Dispose();
RefreshSorting();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
protected void btnRefreshPage_Click(object sender, EventArgs e)
{
// Do nothing...
}
}
}
UControl.ascx
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="UControl.ascx.cs" Inherits="TestUpdatePanel.UControl" %>
<table border="0">
<tr>
<td>
<asp:TextBox ID="txtOrder" runat="server" Enabled="false"></asp:TextBox>
</td>
<td>
<asp:Label ID="lblTest" runat="server"></asp:Label>
</td>
<td>
<asp:TextBox ID="txtTest" runat="server"></asp:TextBox>
</td>
<td>
<asp:Button ID="btnMoveDown" runat="server" Text="Down" OnClick="btnMoveDown_Click" />
</td>
<td>
<asp:Button ID="btnMoveUp" runat="server" Text="Up" OnClick="btnMoveUp_Click" />
</td>
<td>
<asp:Button ID="btnRemove" runat="server" Text="Remove" OnClick="btnRemove_Click" />
</td>
</tr>
</table>
<hr />
UControl.ascx.cs
using System;
namespace TestUpdatePanel
{
public class UControlEventArgs : System.EventArgs
{
public Int32 ID { get; }
public UControlEventArgs(Int32 id)
{
ID = id;
}
}
public partial class UControl : System.Web.UI.UserControl
{
public String Label
{
get { return lblTest.Text; }
set { lblTest.Text = value; }
}
public Int32 Order
{
get { return Convert.ToInt32(txtOrder.Text); }
set { txtOrder.Text = value.ToString(); }
}
private Boolean _IsFirst;
public Boolean IsFirst
{
get { return _IsFirst; }
set
{
_IsFirst = value;
btnMoveUp.Enabled = !_IsFirst;
}
}
private Boolean _IsLast;
public Boolean IsLast
{
get { return _IsLast; }
set
{
_IsLast = value;
btnMoveDown.Enabled = !_IsLast;
}
}
public delegate void MyEventHandler(object sender, UControlEventArgs e);
public event MyEventHandler BtnRemoveClickEvent;
public event MyEventHandler BtnMoveUpClickEvent;
public event MyEventHandler BtnMoveDownClickEvent;
private void OnBtnRemoveClickEvent(int ID)
{
BtnRemoveClickEvent?.Invoke(this, new UControlEventArgs(ID));
}
protected void btnRemove_Click(object sender, EventArgs e)
{
OnBtnRemoveClickEvent(Convert.ToInt32(ID.Replace("C_", "")));
}
private void OnBtnMoveUpClickEvent(int ID)
{
BtnMoveUpClickEvent?.Invoke(this, new UControlEventArgs(ID));
}
protected void btnMoveUp_Click(object sender, EventArgs e)
{
OnBtnMoveUpClickEvent(Convert.ToInt32(ID.Replace("C_", "")));
}
private void OnBtnMoveDownClickEvent(int ID)
{
BtnMoveDownClickEvent?.Invoke(this, new UControlEventArgs(ID));
}
protected void btnMoveDown_Click(object sender, EventArgs e)
{
OnBtnMoveDownClickEvent(Convert.ToInt32(ID.Replace("C_", "")));
}
protected void Page_Load(object sender, EventArgs e)
{
}
}
}
Any suggestions, even for non-issue topics, are welcome.
Thanks to whoever answers me.
It would be very important for me to solve the problem because it is a work project.
Related
I am appending rows using item template
<tr>
<td>
<asp:HyperLink ID="HyperLink1" NavigateUrl="bla" CssClass="display:inherit !important;" Text='<%# someFunction(School.Name,"Name") %>' runat="server" />
</td>
</tr>
the problem with the above one is if someFunction(School.Name,"Name") returns null it appends empty tr, so i want to append tr only if someFunction(School.Name,"Name")!=null
So i tried the below code by adding a if condition but it is not compiling !!
It says school.name is not defined
<% if(someFunction(School.Name,"Name")!=null){
<tr>
<td>
<asp:HyperLink ID="HyperLink1" NavigateUrl="bla" CssClass="display:inherit !important;" Text='<%# someFunction(School.Name,"Name") %>' runat="server" />
</td>
</tr>
} %>
You could take care of it from the code behind.
<td id="tdAppend" runat="server"> Content </td>
if(School.Name == null)
tdAppend.Visible = false;
UPDATED ANSWER:
currentItemIndex = -1;
listView.ItemDataBound += listView_ItemDataBound;
CheckQueryString();
//Hide or show the table header based on id
HtmlControl thControl = listView.FindControl("thAppend") as HtmlControl;
if (thControl != null)
{
if (obj.ID == 12)
{
thControl.Visible = true;
}
else
{
thControl.Visible = false;
for (int i = 0; i < listView.Items.Count; i++)
{
HtmlControl tdControl = listView.Items[i].FindControl("tdSchoolName") as HtmlControl;
if (tdControl != null)
{
tdControl.Visible = false;
}
}
}
}
For convenience:
void listView_ItemDataBound(object sender, ListViewItemEventArgs e)
{
if (e.Item.ItemType == ListViewItemType.DataItem)
{
currentItemIndex++;
ListViewDataItem dataitem = (ListViewDataItem)e.Item;
HtmlTableRow trControl = (HtmlTableRow)e.Item.FindControl("MainTableRow");
if (IsOdd(currentItemIndex))
trControl.BgColor = "DarkGray";
}
}
private bool IsOdd(int value)
{
return value % 2 != 0;
}
It's a pretty straight forward practice.. Handling the ListView.OnItemDataBinding event.
Markup
<%# Import Namespace="MyNamespace" %>
<asp:ListView ID="lview" runat="server" OnItemDataBound="lview_ItemDataBound" ItemPlaceholderID="Placeholder1">
<ItemTemplate>
<tr>
<td><%# ((School)Container.DataItem).Name %></td>
</tr>
</ItemTemplate>
<LayoutTemplate>
<table>
<div id="Placeholder1" runat="server"></div>
</table>
</LayoutTemplate>
</asp:ListView>
Code-Behind
namespace MyNamespace
{
public class Default : Page
{
IEnumerable<School> dataItems {get;set;}
protected void Page_Load(object sender, EventArgs e)
{
dataItems = new School[] { new School() { Name = "School 1" }, new School() { Name = "School 2" }, new School() { Name = null }, new School() { Name = "School 3" } }.AsEnumerable();
lview.DataSource = dataItems;
lview.DataBind();
}
protected void lview_ItemDataBound(object sender, ListViewItemEventArgs e)
{
ListView listview = (ListView)sender;
ListViewItem row = e.Item;
School dataItem = (School)e.Item.DataItem;
if (dataItem.Name == null)
{
row.Visible = false;
}
}
}
public class School
{
public string Name { get; set; }
}
}
personally, I don't usually use tables.. it's a fairly odd-looking layout template.
i have this following code :
<asp:DropDownList ID="dd_SubCategory" Width="160px" runat="server" DataTextField="CATEGORY_NAME" DataValueField="CATEGORY_ID"></asp:DropDownList>
<br />
<asp:Panel ID="pnl_SubCatg" runat="server"></asp:Panel>
<asp:ImageButton ID="Ib_AddSubCategory" runat="server" OnClick="Ib_AddSubCategory_Click" ImageUrl="/images/add.gif" />
protected void Ib_AddSubCategory_Click(object sender, ImageClickEventArgs e)
{
string SelectedCategory="";
if (ctrl_list.Count == 0)
SelectedCategory = dd_SubCategory.SelectedValue;
else
SelectedCategory = Session["Selected_SubCatg"] != null && Session["Selected_SubCatg"].ToString()!=""?Session["Selected_SubCatg"].ToString():((DropDownList)ctrl_list[ctrl_list.Count - 1]).SelectedValue;
try
{
DataRow[] Rows = DataHelper.TicketCategories.Select("PARENT_CATEGORY_ID='" + SelectedCategory + "'");
if (Rows.Length > 0)
{
AddSubCategory(Rows);
}
foreach (Control item in ctrl_list)
pnl_SubCatg.Controls.Add(item);
}
catch (Exception ex)
{ }
}
List<Control> _ctrl_list = null;
List<Control> ctrl_list {
get
{
if (Session["SUB_CATG_LIST"] == null)
{
_ctrl_list = new List<Control>();
Session["SUB_CATG_LIST"] = _ctrl_list;
}
return Session["SUB_CATG_LIST"] as List<Control>;
}
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
Session["SUB_CATG_LIST"] = null;
Session["Selected_SubCatg"] = null;
}
if (ctrl_list.Count > 0)
{
foreach (Control item in ctrl_list)
pnl_SubCatg.Controls.Add(item);
}
}
private void AddSubCategory(DataRow [] Rows)
{
DropDownList dd_SubCategory1 = new DropDownList();
dd_SubCategory1.Width = Unit.Pixel(160);
dd_SubCategory1.DataTextField = "CATEGORY_NAME";
dd_SubCategory1.DataValueField = "CATEGORY_ID";
dd_SubCategory1.ID = Guid.NewGuid().ToString();
dd_SubCategory1.DataSource = Rows.CopyToDataTable();
dd_SubCategory1.DataBind();
dd_SubCategory1.SelectedIndexChanged += dd_SubCategory1_SelectedIndexChanged;
dd_SubCategory1.AutoPostBack = true;
ctrl_list.Add(dd_SubCategory1);
}
void dd_SubCategory1_SelectedIndexChanged(object sender, EventArgs e)
{
Session["Selected_SubCatg"] = ((DropDownList)sender).SelectedValue;
}
i am trying to add a dropdown list containing the subcategories of the last inserted dropdown list , my problem is dd_SubCategory1_SelectedIndexChanged is not firing and i can't get the and the selectedValue of the last dropdownlist is always the same
That is because its dynamically generated and it will lose its state after its rendered on your page.
To access the dropdown and its related events and properties, you will need to recreate it everytime your page is postback.
Hope its clear enough.
I've a gridview with webcontrols(Textbox,Button in footer). Dynamically I need to create any number of gridviews by the following code. But only 1 gridview is created. And also the problem is the button event is not firing
public void btn_Click(object sender, EventArgs e)
{
GridView gv = new GridView();
gv.ID = sender.ToString();
}
inside the class. How to fire this event?
This is the code I used to create gridview.
protected void btnAddGrid_Click(object sender,EventArgs e)
{
int count = Convert.ToInt32(Session["count"]);
DataTable dt=(DataTable)ViewState["CurrentTableforCommonDetails"];
GridView gv = new GridView();
gv.ID = "GridView" + count;
gv.AutoGenerateColumns = false;
if (dt.Rows.Count > 0)
{
for (int i = 0; i < dt.Columns.Count; i++)
{
TemplateField tmpfld = new TemplateField();
tmpfld.HeaderText = dt.Columns[i].ColumnName.ToString();
tmpfld.ItemTemplate =new DynamicTemplateField();
if (i == 0)
{
tmpfld.FooterTemplate = new DynamicTemplateField1();
}
gv.Columns.Add(tmpfld);
}
}
gv.Visible = true;
gv.ShowHeaderWhenEmpty = true;
gv.ShowFooter = true;
placegridview.Controls.Add(gv);
gv.DataSource = dt;
gv.DataBind();
count++;
Session["count"] = count;
}
public class DynamicTemplateField : ITemplate
{
public void InstantiateIn(System.Web.UI.Control container)
{
//define the control to be added , i take text box as your need
System.Web.UI.WebControls.TextBox txt1 = new System.Web.UI.WebControls.TextBox();
txt1.ID = "txt1";
txt1.Width = 50;
container.Controls.Add(txt1);
}
}
public class DynamicTemplateField1 : ITemplate
{
public void InstantiateIn(System.Web.UI.Control container)
{
//define the control to be added , i take text box as your need
System.Web.UI.WebControls.Button btn = new System.Web.UI.WebControls.Button();
btn.ID = "btn1";
btn.Click += new EventHandler(btn_Click);
btn.UseSubmitBehavior = false;
btn.Text = "Add New";
container.Controls.Add(btn);
}
public void btn_Click(object sender, EventArgs e)
{
GridView gv = new GridView();
gv.ID = sender.ToString();
}
}
This generally involves tracking (or maintaining state which stores) the fact that you have a dynamic control, and adding that control to the control tree really early on in the page lifecycle. The following example is not relevant to your question, but it demonstrates how to deal with dynamic controls
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebApp.DynamicControls2
{
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
ControlsCount = 0;
}
else
{
for (int i = 0, j = ControlsCount; i < j; i++)
{
CreateControl();
}
}
}
protected override void LoadViewState(object savedState)
{
base.LoadViewState(savedState);
}
int ControlsCount
{
get
{
if (ViewState["ControlsCount"] == null)
{
int count = 0;
ViewState["ControlsCount"] = count;
return count;
}
return (int)ViewState["ControlsCount"];
}
set
{
ViewState["ControlsCount"] = value;
}
}
protected void btnAdd_Click(object sender, EventArgs e)
{
CreateControl(true);
}
protected void btnCount_Click(object sender, EventArgs e)
{
}
void CreateControl(bool UpdateCount = false)
{
TextBox tbx = new TextBox();
Button btn = new Button() { Text = "Get Time" };
btn.Click += btn_Click;
Literal br = new Literal() { Text = "<br/>" };
var ctls = phContainer.Controls;
ctls.Add(tbx);
ctls.Add(btn);
ctls.Add(br);
if (UpdateCount) ControlsCount++;
}
void btn_Click(object sender, EventArgs e)
{
Button btn = (Button)sender;
Control parent = btn.Parent;
int index = parent.Controls.IndexOf(btn);
TextBox tbx = parent.Controls[index - 1] as TextBox;
tbx.Text = DateTime.Now.ToLongTimeString();
}
}
}
The webform associated with this code is:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApp.DynamicControls2.WebForm1" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Dynamic Controls</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Button ID="btnAdd" runat="server" Text="Add" OnClick="btnAdd_Click" />
<asp:Button ID="btnCount" runat="server" Text="Get Count" OnClick="btnCount_Click" />
</div>
<br />
<br />
<div>
<asp:PlaceHolder ID="phContainer" runat="server"></asp:PlaceHolder>
</div>
</form>
</body>
</html>
You should adapt your code likewise to ensure this effect.
If you want to understand terms such as tracking or control tree read the following article series. http://weblogs.asp.net/infinitiesloop/TRULY-Understanding-Dynamic-Controls-_2800_Part-1_2900_
Update 1:
There are various cases and it can become complicated based on requirement. The code for the most basic approach is shown below:
Webform (aspx):
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm3.aspx.cs" Inherits="WebApp.DynamicGridViewWithTemplateField.WebForm3" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
<asp:Button ID="btn1" runat="server" Text="Clickme" />
</div>
</form>
</body>
</html>
Code-behind:
using System;
using System.Collections.Generic;
using System.Data;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebApp.DynamicGridViewWithTemplateField
{
public partial class WebForm3 : System.Web.UI.Page
{
protected override void LoadViewState(object savedState)
{
base.LoadViewState(savedState);
CreateGrid();
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
if (!IsPostBack)
{
CreateGrid();
ViewState["foo"] = "foo"; //forcing viewstate
}
}
}
private static DataTable GetNames()
{
DataTable tbl = new DataTable();
tbl.Columns.Add(new DataColumn("Name"));
List<string> names = new List<string>() { "Arun", "Samit", "Jermy", "John" };
names.ForEach(x =>
{
var row = tbl.NewRow();
row[0] = x;
tbl.Rows.Add(row);
});
return tbl;
}
void CreateGrid()
{
GridView gv = new GridView();
gv.AutoGenerateColumns = false;
gv.Columns.Add(new BoundField() {
HeaderText="Names",
DataField="Name"
});
gv.Columns.Add(new TemplateField()
{
ItemTemplate = new TextTemplateField(),
HeaderText = "Remarks"
});
gv.Columns.Add(new TemplateField()
{
ItemTemplate = new DropDownTemplateField(),
HeaderText="Choose option"
});
gv.Columns.Add(new TemplateField()
{
ItemTemplate = new ButtonTemplateField()
});
gv.RowCommand += (sndr, evt) =>
{
if (evt.CommandName == "foo")
{
Control ctrl = (Control)evt.CommandSource;
GridViewRow gvRow = (GridViewRow)ctrl.Parent.Parent;
var tbx = gvRow.FindControl("tbx1") as TextBox;
tbx.Text = DateTime.Now.ToLongTimeString();
}
};
gv.DataSource = GetNames();
gv.DataBind();
PlaceHolder1.Controls.Add(gv);
}
}
}
The ButtonTemplateField, DropDownTemplateField and TextTemplateField are simple templates, and correspondingly contain a Button, DropDownList, and TextBox respectively. Nothing really fancy there.
public class DropDownTemplateField : ITemplate
{
int[] options = new int[] { 1, 2, 3, 4 };
public void InstantiateIn(Control container)
{
DropDownList ddl = new DropDownList();
ddl.DataSource = options;
foreach (int value in options)
{
ddl.Items.Add(new ListItem(value.ToString(), value.ToString()));
}
container.Controls.Add(ddl);
}
}
public class ButtonTemplateField : ITemplate
{
public void InstantiateIn(Control container)
{
Button btn = new Button();
btn.CommandName = "foo";
btn.Text = "Click me";
container.Controls.Add(btn);
}
}
public class TextTemplateField : ITemplate
{
public void InstantiateIn(Control container)
{
TextBox tbx = new TextBox();
tbx.ID = "tbx1";
container.Controls.Add(tbx);
}
}
I'm new to coding, hope some can help me a bit, I got stuck at retrieving data from my Dynamically added Text boxes in ASP.NET.
I Master Site and a Content site. I have added some buttons to the content site there are adding or removing the textboxes, after what's needed by the user.
My problem is, that i'm not sure how to retrieve the data correct. hope some body can help me on the way.
My Content site:
<%# Page Title="" Language="C#" MasterPageFile="~/main.master" AutoEventWireup="true" CodeFile="CreateRMA.aspx.cs" Inherits="CreateRMA" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="mainsite" Runat="Server">
<div id="div_fortext" class="div_fortext">
<p class="header2">
Opret RMA Sag
</p>
<p class="text1">
Her Kan de oprette alt det udstyr der skal sendes til reperation hos zenitel.
</p>
</div>
<div id="div_insert_devices" runat="server">
</div>
// 3 buttons one who add, one who remove textboxes and a submit button
<asp:Button ID="btnAddRow" runat="server" Text="Add Row" CssClass="butten1" OnClick="btnAddRow_Click" />
<asp:Button ID="btnRemoveRow" runat="server" Text="Remove Row" CssClass="butten1" OnClick="btnRemoveRow_Click" />
<asp:Button ID="btnSubmit" runat="server" Text="Submit" CssClass="butten1" OnClick="btnSubmit_Click" />
</asp:Content>
My C# code behind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class CreateRMA : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
ViewState["DeviceCount"] = ViewState["DeviceCount"] == null ? 1 : ViewState["DeviceCount"];
InsertLine();
}
}
private void InsertLine()
{
int DeviceCount = int.Parse(ViewState["DeviceCount"].ToString());
for (int i = 0; i < DeviceCount; i++)
{
LiteralControl text = new LiteralControl("<div class=\"divPerDevice\">");
div_insert_devices.Controls.Add(text);
TextBox txtbox = new TextBox();
txtbox.ID = "serial" + i;
txtbox.CssClass = "textbox1";
txtbox.Attributes.Add("runat", "Server");
div_insert_devices.Controls.Add(txtbox);
text = new LiteralControl("</div>");
div_insert_devices.Controls.Add(text);
}
}
protected void btnAddRow_Click(object sender, EventArgs e)
{
int count = int.Parse(ViewState["DeviceCount"].ToString());
count++;
ViewState["DeviceCount"] = count;
InsertLine();
}
protected void btnRemoveRow_Click(object sender, EventArgs e)
{
int count = int.Parse(ViewState["DeviceCount"].ToString());
count--;
ViewState["DeviceCount"] = count;
InsertLine();
}
protected void btnSubmit_Click(object sender, EventArgs e)
{
// Submit - save the textboxes to Strings ??? Can any body help
}
}
((TextBox)div_insert_devices.FindControl("txtboxname")).Text
Try this one
you can use the following code
protected void btnSubmit_Click(object sender, EventArgs e)
{
// Submit - save the textboxes to Strings ??? Can any body help
int DeviceCount = int.Parse(ViewState["DeviceCount"].ToString());
for (int i = 0; i < DeviceCount; i++)
{
TextBox txtbx= (TextBox)div_insert_devices.FindControl("serial" + i);
if(txtbx!=null)
{
var value= txtbx.Text;
}
}
}
The way i would attempt this is like the following:
protected void btnSubmit_Click(object sender, EventArgs e)
{
foreach (Control control in div_insert_devices.Controls){
if (control.GetType() == typeof(textbox)){
Textbox myDynTextbox = (Textbox)control;
Var myString = myDynTextbox.Text;
Please note this code can be simplyfied further but, i have written it this was so you understand how it would work, and my advise would be to store all the strings in a collection of Strings, making it easier to maintain.
}
}
}
Kush
Why don't you use javascript to save the value of textbox. just hold the value in some hidden field and bind it everytime when you need it.
Hi I found the solution after some time here... I did not got any of examples to work that you have provided. sorry.
But I almost started from scratch and got this to work precis as I wanted :)
My Content Site:
<%# Page Title="" Language="C#" MasterPageFile="~/main.master" AutoEventWireup="true" CodeFile="CreateRMA.aspx.cs" Inherits="CreateRMA" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="mainsite" Runat="Server">
<div id="div_fortext" class="div_fortext">
<p class="header2">
Opret RMA Sag
</p>
<p class="text1">
Some TEXT
</p>
</div>
</div>
<asp:Button ID="btnAddRow" runat="server" Text="Add Row" CssClass="butten1" OnClick="btnAddRow_Click" />
<asp:Button ID="btnRemoveRow" runat="server" Text="Remove Row" CssClass="butten1" OnClick="btnRemoveRow_Click" />
<asp:Button ID="btnSubmit" runat="server" Text="Submit" CssClass="butten1" OnClick="btnSubmit_Click" />--%>
<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
<asp:PlaceHolder runat="server" id="DynamicDevices"></asp:PlaceHolder>
<asp:Button id="btnAddTextBox" runat="server" text="Tilføj" CssClass="butten1" OnClick="btnAddTextBox_Click" />
<asp:Button id="btnRemoveTextBox" runat="server" text="Fjern" CssClass="butten1" OnClick="btnRemoveTextBox_Click" />
<asp:Button runat="server" id="Submit" text="Submit" CssClass="butten1" OnClick="Submit_Click" />
<br /><asp:Label runat="server" id="MyLabel"></asp:Label>
</asp:Content>
My C# code behind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Data;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class CreateRMA : System.Web.UI.Page
{
static int myCount = 1;
private TextBox[] dynamicTextBoxes;
private TextBox[] Serial_arr;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
myCount = 1;
}
}
protected void Page_Init(object sender, EventArgs e)
{
Control myControl = GetPostBackControl(this.Page);
if (myControl != null)
{
if (myControl.ID.ToString() == "btnAddTextBox")
{
myCount = myCount >= 30 ? 30 : myCount + 1;
}
if (myControl.ID.ToString() == "btnRemoveTextBox")
{
myCount = myCount <= 1 ? 1 : myCount - 1;
}
}
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
dynamicTextBoxes = new TextBox[myCount];
Serial_arr = new TextBox[myCount];
int i;
for (i = 0; i < myCount; i += 1)
{
LiteralControl literalBreak = new LiteralControl("<div>");
DynamicDevices.Controls.Add(literalBreak);
TextBox Serial = new TextBox();
Serial.ID = "txtSerial" + i.ToString();
Serial.CssClass = "";
DynamicDevices.Controls.Add(Serial);
Serial_arr[i] = Serial;
TextBox textBox = new TextBox();
textBox.ID = "myTextBox" + i.ToString();
DynamicDevices.Controls.Add(textBox);
dynamicTextBoxes[i] = textBox;
literalBreak = new LiteralControl("</div>");
DynamicDevices.Controls.Add(literalBreak);
}
}
public static Control GetPostBackControl(Page thePage)
{
Control mycontrol = null;
string ctrlname = thePage.Request.Params.Get("_EVENTTARGET");
if (((ctrlname != null) & (ctrlname != string.Empty)))
{
mycontrol = thePage.FindControl(ctrlname);
}
else
{
foreach (string item in thePage.Request.Form)
{
Control c = thePage.FindControl(item);
if (((c) is System.Web.UI.WebControls.Button))
{
mycontrol = c;
}
}
}
return mycontrol;
}
protected void Submit_Click(object sender, EventArgs e)
{
int deviceCount = Serial_arr.Count();
DataSet ds = new DataSet();
ds.Tables.Add("Devices");
ds.Tables["Devices"].Columns.Add("Serial", System.Type.GetType("System.String"));
ds.Tables["Devices"].Columns.Add("text", System.Type.GetType("System.String"));
for (int x = 0; x < deviceCount; x++)
{
DataRow dr = ds.Tables["Devices"].NewRow();
dr["Serial"] = Serial_arr[x].Text.ToString();
dr["text"] = dynamicTextBoxes[x].Text.ToString();
ds.Tables["Devices"].Rows.Add(dr);
}
//MyLabel.Text = "der er " + deviceCount +" Devices<br />";
//foreach (TextBox tb in Serial_arr)
//{
// MyLabel.Text += tb.Text + " :: ";
//}
//MyLabel.Text += "<br />";
//foreach (TextBox tb in dynamicTextBoxes)
//{
// MyLabel.Text += tb.Text + " :: ";
//}
}
protected void btnAddTextBox_Click(object sender, EventArgs e)
{
}
protected void btnRemoveTextBox_Click(object sender, EventArgs e)
{
}
}
Thanks For all the help anyway :)
Hope somebody can use this.
Best regards Kasper :)
I have a small User Control defined as:
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="CompanyTree.ascx.cs" Inherits="RivWorks.Web.UserControls.CompanyTree" %>
<div class="PrettyTree">
<asp:TreeView runat="server"
ID="companyTree"
OnSelectedNodeChanged="SelectedNodeChanged"
OnAdaptedSelectedNodeChanged="SelectedNodeChanged" >
</asp:TreeView>
<asp:Label runat="server" ID="currentParentID" Text="" Visible="false" />
<asp:Label runat="server" ID="currentCompanyID" Text="" Visible="false" />
<asp:Label runat="server" ID="currentExpandDepth" Text="" Visible="false" />
<asp:Label runat="server" ID="currentValuePath" Text="" Visible="false" />
<asp:Label runat="server" ID="currentParentValuePath" Text="" Visible="false" />
<asp:Label runat="server" ID="currentCompanyUser" Text="" Visible="false" />
</div>
For some reason, the OnSelectedNodeChanged and OnAdaptedSelectedNodeChanged events do not fire when I click on a node in the tree. I’ve been googling for the last hour and have not found anything amiss.
Here are my event handlers in the code behind.
#region Event Handlers
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
LoadCompanyTree();
TreeNode currentNode = companyTree.SelectedNode;
CompanyID = currentNode.Value;
ValuePath = currentNode.ValuePath;
if (currentNode.Parent != null)
{
ParentCompanyID = currentNode.Parent.Value;
ParentValuePath = currentNode.Parent.ValuePath;
}
else
{
ParentCompanyID = "";
ParentValuePath = "";
}
ExpandDepth = currentNode.Depth.ToString();
LoadCompany();
}
}
protected void SelectedNodeChanged(object sender, EventArgs e)
{
TreeNode currentNode = companyTree.SelectedNode;
CompanyID = currentNode.Value;
ValuePath = currentNode.ValuePath;
if (currentNode.Parent != null)
{
ParentCompanyID = currentNode.Parent.Value;
ParentValuePath = currentNode.Parent.ValuePath;
}
else
{
ParentCompanyID = "";
ParentValuePath = "";
}
ExpandDepth = currentNode.Depth.ToString();
LoadCompany();
}
#endregion
I am also including the code for building the tree. My data structure is based off of http://articles.sitepoint.com/article/hierarchical-data-database.
private void LoadCompanyTree()
{
DataTable dtTree = RivWorks.Data.Companies.GetTree();
companyTree.Nodes.Clear();
companyTree.Nodes.Add(RivWorks.Web.Tree.BuildTree(dtTree, Page));
companyTree.ExpandDepth = 1;
companyTree.Nodes[0].Selected = true;
companyTree.Nodes[0].Select();
companyTree.ShowLines = true;
companyTree.RootNodeStyle.ImageUrl = Page.ResolveUrl(#"~/images/tree/root.png");
companyTree.ParentNodeStyle.ImageUrl = Page.ResolveUrl(#"~/images/tree/parent.png");
companyTree.LeafNodeStyle.ImageUrl = Page.ResolveUrl(#"~/images/tree/leaf.png");
companyTree.SelectedNodeStyle.Font.Bold = true;
companyTree.SelectedNodeStyle.Font.Italic = true;
if (CompanyID.Length > 0)
{
for (int i = 0; i < companyTree.Nodes.Count; i++)
{
if (companyTree.Nodes[i].Value.Equals(CompanyID, StringComparison.CurrentCultureIgnoreCase))
{
companyTree.ExpandDepth = companyTree.Nodes[i].Depth;
ValuePath = companyTree.Nodes[i].ValuePath;
companyTree.Nodes[i].Selected = true;
companyTree.Nodes[i].Select();
}
}
}
}
internal static TreeNode BuildTree(DataTable dtTree, System.Web.UI.Page myPage)
{
int left = 0;
int right = 0;
int index = 0;
Stack<int> rightStack = new Stack<int>();
Stack<TreeNode> treeStack = new Stack<TreeNode>();
TreeNode rootNode = new TreeNode(dtTree.Rows[index]["CompanyName"].ToString(), dtTree.Rows[index]["CompanyID"].ToString());
while (index < dtTree.Rows.Count)
{
left = Convert.ToInt32(dtTree.Rows[index]["left"]);
right = Convert.ToInt32(dtTree.Rows[index]["right"]);
if (rightStack.Count > 0)
{
while (rightStack.Peek() < right)
{
rightStack.Pop();
treeStack.Pop();
}
}
if (treeStack.Count == 0)
{
treeStack.Push(rootNode);
}
else
{
TreeNode treeNode = new TreeNode(dtTree.Rows[index]["CompanyName"].ToString(), dtTree.Rows[index]["CompanyID"].ToString());
treeStack.Peek().ChildNodes.Add(treeNode);
treeStack.Push(treeNode);
}
rightStack.Push(right);
index++;
}
return rootNode;
}
When I put this in an ASPX page it works fine. When I moved it to an ASCX User Control the event no longer fires! Any tips/suggestions to get the event to fire?
TIA
NOTE:
I am using the CSS Friendly Control Adapters found on CodePlex. http://cssfriendly.codeplex.com/workitem/5519?PendingVoteId=5519 is a bug report of the event not raising in User Control (.ascx). I've added the suggested code plus more and it still does not fire.
<MasterPage>
<Page>
<ContentHolder>
<User Control> <-- this should handle the event!
<TreeView with CSSFriendly Adapter>
Code in the adapter:
public void RaiseAdaptedEvent(string eventName, EventArgs e)
{
string attr = "OnAdapted" + eventName;
if ((AdaptedControl != null) && (!String.IsNullOrEmpty(AdaptedControl.Attributes[attr])))
{
string delegateName = AdaptedControl.Attributes[attr];
Control methodOwner = AdaptedControl.Parent;
MethodInfo method = methodOwner.GetType().GetMethod(delegateName);
if (method == null)
{
methodOwner = AdaptedControl.Page;
method = methodOwner.GetType().GetMethod(delegateName);
}
// 2010.06.21 - keith.barrows - added to (hopefully) handle User Control (ASCX) coding...
// http://forums.asp.net/t/1249501.aspx
if (method == null)
{
Control parentUserControl = FindParentUserControl(AdaptedControl.Parent);
if (parentUserControl != null)
{
methodOwner = parentUserControl;
method = methodOwner.GetType().GetMethod(delegateName);
}
}
// 2010.06.21 - keith.barrows - added to (hopefully) handle User Control (ASCX) coding...
// http://cssfriendly.codeplex.com/workitem/5519?ProjectName=cssfriendly
if (method == null)
{
methodOwner = AdaptedControl.NamingContainer;
method = methodOwner.GetType().GetMethod(delegateName);
}
if (method == null)
{
methodOwner = AdaptedControl.Parent;
method = methodOwner.GetType().GetMethod(delegateName);
}
if (method != null)
{
object[] args = new object[2];
args[0] = AdaptedControl;
args[1] = e;
method.Invoke(methodOwner, args);
}
}
}
private Control FindParentUserControl(Control control)
{
if (control.Parent == null)
return null;
if (control.Parent is UserControl)
return control.Parent;
return FindParentUserControl(control.Parent);
}
Am I missing a delegate or event definition? The Adapted Control is JUST NOT FINDING the method to call!
Quite by accident I found a solution that does work. Don't ask me why but I am dying to find out!
In my ASPX page code-beside I added this method signature:
protected void SelectedNodeChanged(object sender, EventArgs e)
{
}
And now the RaiseAdaptedEvent event finds the event handler in the ASCX file!!
Before I mark this as the answer - does anyone have any clue why this would work this way?
I have found that the CSS Friendly has some issues with calling protected methods. This is how I fix this:
In the class WebControlAdapterExtender, method WebControlAdapterExtender ( line 161), I added this line:
if (method == null)
{
method = methodOwner.GetType().GetMethod(delegateName, BindingFlags.Instance |
BindingFlags.NonPublic);
}
and works for me.
Hope this helps.