I am completly new in asp.net and I'm having some problems with it.
I created litle web form for demo and learning and I have some problems with it. Hopefuly you can help me :)
What I want is that:
when I click on "Kill X" button in table, I get "You pressed button Kill X" message in label "lblMsg". I Also want that I get table with new data.
when I click "Load" button, I need to get additional rows in the table. For example now when page loads there is 10 rows in table and when I click "Load" I nedd to get additional 10 rows at the end into the same table.
P.S:
I would be grateful for some tutorial how to deal with events in asp.net.
Bellow is the code:
WebForm1.aspx
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="HelpdeskOsControl.WebForm1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<asp:Panel ID="Panel1" runat="server" Height="465px" Width="417px">
<asp:Table ID="Processes" runat="server" Height="20px" Width="400px" CssClass="tablesorter">
<asp:TableHeaderRow ID="ProcessesHeader" runat="server"
TableSection="TableHeader">
<asp:TableHeaderCell ID="TableHeaderCell1" runat="server">Name</asp:TableHeaderCell>
<asp:TableHeaderCell ID="TableHeaderCell2" runat="server">CPU</asp:TableHeaderCell>
<asp:TableHeaderCell ID="TableHeaderCell3" runat="server">Memory</asp:TableHeaderCell>
<asp:TableHeaderCell ID="TableHeaderCell4" runat="server"></asp:TableHeaderCell>
</asp:TableHeaderRow>
</asp:Table>
<asp:Panel ID="Panel2" runat="server">
<asp:Button ID="btnLoad" runat="server" onclick="btnLoad_Click" Text="Load" />
<asp:Button ID="btnClear" runat="server" onclick="btnClear_Click"
Text="Clear" />
<asp:Label ID="lblMsg" runat="server" Text="Label"></asp:Label>
</asp:Panel>
</asp:Panel>
</form>
</body>
</html>
WebForm1.aspx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace HelpdeskOsControl
{
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
GenerateTable(getTestData());
}
private List<string> getTestData()
{
List<string> tData = new List<string>();
Random rand = new Random();
for (int i = 0; i < 10; i++)
{
tData.Add("proc" + i + "_" + rand.Next(100) + "_" + rand.Next(100));
}
return tData;
}
protected void btnClear_Click(object sender, EventArgs e)
{
for (int i = Processes.Rows.Count; i > 1; i--)
{
Processes.Rows.RemoveAt(i - 1);
}
}
protected void btnLoad_Click(object sender, EventArgs e)
{
GenerateTable(getTestData());
}
protected void btnKill_Click(object sender, EventArgs e)
{
lblMsg.Text = "You pressed button " + ((Button)sender).Text;
}
private void GenerateTable(List<string> list)
{
int st = 0;
foreach (string line in list)
{
TableRow tr = new TableRow();
Processes.Controls.Add(tr);
foreach (String str in line.Split('_'))
{
int index = tr.Cells.Add(new TableCell());
tr.Cells[index].Text = str;
}
Button b = new Button();
b.Text = "Kill " + st;
b.ID = "btnKill_" + st;
b.Click += new EventHandler(btnKill_Click);
TableCell tc = new TableCell();
tc.Controls.Add(b);
tr.Cells.Add(tc);
tr.TableSection = TableRowSection.TableBody;
st++;
}
Processes.BorderStyle = BorderStyle.Solid;
Processes.GridLines = GridLines.Both;
Processes.BorderWidth = 2;
}
}
}-
I understand this is your first time with ASP.NET and want to help you learn more about its potentials.
First of all, I would replace the code you wrote with data binding, which is a way to easily build tables without having to write methods like your generateTable. ASP.NET takes care of building the table by itself. It will take me a while to illustrate you full code for achieving this, but I hope you can grab the documentation and start learning with my help.
The key control is GridView. It can be populated using a two-lines code fragment
protected override OnLoad(EventArgs e)
{
if (!IsPostback) DataBind();
}
protected override void OnDataBind(EventArgs e)
{
gridView.DataSource = getTestData();
gridView.DataBind();
}
You must first configure columns in layout. The articles about GridView deal with this, and you can add a button for each row.
Now,
you can set the buttons as command buttons, thus not only raising the Click event, but, more important, the Command event which takes a name and an argument. That's where you can inject your code. For example
<asp:Button id="btnSomething" CommandArgument="[procId]" CommandName="kill" OnCommand="myCommandHandler" />
protected void myCommandHandler(object sender, CommandEventArgs e)
{
if (e.CommandName=="kill")
{
killProcess(e.CommandArgument);
DataBind(); //MOST IMPORTANT
}
}
Hope to have been of help. I wrote this code by hand, so please understand me if it will not work immediately
You need to store the state of the table between page loads and regenerate it as the dynamic controls are not stored between requests. (An advantage of using a ListView, DataGrid etc.).
public partial class WebForm1 : System.Web.UI.Page
{
private List<string> CurrentTestData
{
get
{
if (ViewState["CurrentTestData"] == null)
return new List<string>();
else
return (List<string>)ViewState["CurrentTestData"];
}
set
{
ViewState["CurrentTestData"] = value;
}
}
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
CurrentTestData = getTestData();
GenerateTable(CurrentTestData);
}
else
GenerateTable(CurrentTestData);
}
private List<string> getTestData()
{
List<string> tData = new List<string>();
Random rand = new Random();
for (int i = 0; i < 10; i++)
{
tData.Add("proc" + (CurrentTestData.Count + i) + "_" + rand.Next(100) + "_" + rand.Next(100));
}
return tData;
}
protected void btnClear_Click(object sender, EventArgs e)
{
ClearTheTable();
CurrentTestData = null;
}
protected void btnLoad_Click(object sender, EventArgs e)
{
var CombinedTestData = CurrentTestData;
CombinedTestData.AddRange(getTestData());
CurrentTestData = CombinedTestData;
GenerateTable(CurrentTestData);
}
protected void btnKill_Click(object sender, EventArgs e)
{
lblMsg.Text = "You pressed button " + ((Button)sender).Text;
}
private void GenerateTable(List<string> list)
{
ClearTheTable();
int st = 0;
foreach (string line in list)
{
TableRow tr = new TableRow();
Processes.Controls.Add(tr);
foreach (String str in line.Split('_'))
{
int index = tr.Cells.Add(new TableCell());
tr.Cells[index].Text = str;
}
Button b = new Button();
b.Text = "Kill " + st;
b.ID = "btnKill_" + st;
b.Click += new EventHandler(btnKill_Click);
TableCell tc = new TableCell();
tc.Controls.Add(b);
tr.Cells.Add(tc);
tr.TableSection = TableRowSection.TableBody;
st++;
}
Processes.BorderStyle = BorderStyle.Solid;
Processes.GridLines = GridLines.Both;
Processes.BorderWidth = 2;
}
private void ClearTheTable()
{
for (int i = Processes.Rows.Count; i > 1; i--)
{
Processes.Rows.RemoveAt(i - 1);
}
}
}
Two nice links for you:
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.button.click.aspx
http://www.youcanlearnseries.com/Programming%20Tips/CSharp/SetEvents.aspx
Related
Currently I'm working on a webform app and I populate the DevExpress grid on selected value from a ASPxComboBox. I have this part working no problem. However my requirement is to refresh the grid if there is any new data added into the database so the users can see this. So I've added a button and on the click event I try to refresh the data but the grid doesn't refresh. If I step through the code I can see that the new values from the database are there in my DataTable. I can't seem to figure out what could be causing the grid to not refresh. Any help would be highly appreciated.
This is what I have so far
SelectedIndexChangedEvent
protected void TrainingOptions_SelectedIndexChanged(object sender, EventArgs e)
{
ASPxComboBox ddl = (ASPxComboBox)sender;
string[] parameters = { ddl.SelectedItem.Value.ToString() };
TrainingGrid.DataSource = dto.PopulateTrainingData(parameters);
TrainingGrid.DataBind();
}
ButtonClickEvent
protected void Refresh_Click(object sender, EventArgs e)
{
string[] parameters = { TrainingOptions.SelectedItem.Value.ToString() };
TrainingGrid.DataSource = dto.PopulateTrainingData(parameters);
TrainingGrid.DataBind();
}
PopulateTrainingDara
public DataTable PopulateTrainingData(params string[] parameters)
{
//Loop through DataTable Here
...
HttpContext.Current.Session["GridDT"] = mainTable;
return mainTable;
}
DataBinding
protected void TrainingGrid_DataBinding(object sender, EventArgs e)
{
TrainingGrid.DataSource = Session["GridDT"];
}
Page_LoadEvent
if (!IsPostBack)
{
DataTable dropDownOptions = dto.GetTrainingData("MyQuery");
//Add datasource to TrainingOptions dropdown
TrainingOptions.DataSource = dropDownOptions;
TrainingOptions.Text = "Please choose";
TrainingOptions.TextField = "ID";
TrainingOptions.DataBindItems();
}
Markup
<dx:ASPxComboBox ID="TrainingOptions" runat="server" ValueType="System.String" OnSelectedIndexChanged="TrainingOptions_SelectedIndexChanged" CssClass="combo-box"></dx:ASPxComboBox>
<dx:ASPxGridView ID="TrainingGrid" runat="server" OnHtmlDataCellPrepared="TrainingGrid_HtmlDataCellPrepared" OnDataBinding="TrainingGrid_DataBinding"></dx:ASPxGridView>
<dx:ASPxButton ID="Refresh" runat="server" Text="Refresh" OnClick="Refresh_Click" AutoPostBack="false"></dx:ASPxButton>
Note: I am not populating the grid in the Page_Load event.
If any other information is required please let me know.
Ok, so I've recreated your example with the latest trial version of DevExpress Suite. I removed unnecessary code and this is the code that works in my case:
public partial class DevExpress : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
DataTable dropDownOptions = new DataTable();
dropDownOptions.Columns.Add("id");
DataRow row = dropDownOptions.NewRow();
row["id"] = 1;
dropDownOptions.Rows.Add(row);
row = dropDownOptions.NewRow();
row["id"] = 2;
dropDownOptions.Rows.Add(row);
dropDownOptions.AcceptChanges();
TrainingOptions.DataSource = dropDownOptions;
TrainingOptions.Text = "Please choose";
TrainingOptions.TextField = "ID";
TrainingOptions.DataBindItems();
}
}
protected void Refresh_Click(object sender, EventArgs e)
{
string[] parameters = { TrainingOptions.SelectedItem.Value.ToString() };
TrainingGrid.DataSource = PopulateTrainingData(parameters);
TrainingGrid.DataBind();
}
protected void TrainingOptions_SelectedIndexChanged(object sender, EventArgs e)
{
ASPxComboBox ddl = (ASPxComboBox)sender;
string[] parameters = { ddl.SelectedItem.Value.ToString() };
TrainingGrid.DataSource = PopulateTrainingData(parameters);
TrainingGrid.DataBind();
}
public DataTable PopulateTrainingData(params string[] parameters)
{
DataTable mainTable = (DataTable)Session["GridDT"] ?? new DataTable();
if (!mainTable.Columns.Contains("id"))
{
mainTable.Columns.Add("id");
}
DataRow row = mainTable.NewRow();
row["id"] = parameters[0];
mainTable.Rows.Add(row);
mainTable.AcceptChanges();
HttpContext.Current.Session["GridDT"] = mainTable;
return mainTable;
}
}
And the aspx:
<%# Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="DevExpress.aspx.cs" Inherits="WebApplication1.DevExpress" %>
<%# Register Assembly="DevExpress.Web.v15.2, Version=15.2.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" Namespace="DevExpress.Web" TagPrefix="dx" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<dx:ASPxComboBox ID="TrainingOptions" runat="server" ValueType="System.String" OnSelectedIndexChanged="TrainingOptions_SelectedIndexChanged" AutoPostBack="true" CssClass="combo-box"></dx:ASPxComboBox>
<dx:ASPxGridView ID="TrainingGrid" runat="server"></dx:ASPxGridView>
<dx:ASPxButton ID="Refresh" runat="server" Text="Refresh" OnClick="Refresh_Click"></dx:ASPxButton>
</asp:Content>
If this is not working for you you should check which version of DevExpress controls are you using and maybe update them if its possible. Or maybe you are doing something more which you didn't post here.
Last page button code works if put inside of the If (!this.isPostBack), so I did a lot of research to try and understand the cause of my problem but could not figure out my specific issue, looked through all threads regarding this on stackoverflow as well but to no luck. What am I missing?
Also, I could not get the Excel export to work, I tried 3 different approaches that all led to a OutOfMemoryException, the latest is still in the method but commented away for further laboration.
http://i.imgur.com/uoyIhdB.jpg
ASPX Code
<%# Page Language="C#" AutoEventWireup="true"
CodeBehind="TestWebFormView.aspx.cs" Inherits="NameSpace.TestWebFormView"
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<%--Form--%>
<form id="form1" runat="server" visible="true">
<asp:Hidden
<div>
<%--GridView--%>
<asp:GridView ID="GridView" AllowPaging="true" PageSize="5" OnPageIndexChanging="GridView_PageIndexChanging" runat="server" AutoGenerateColumns="true" DataKeyNames="Column1, Column2, Column3, Column4, Column5, Column6, Column7, Column8, Column9, Column10, Column11, Column12, Column13, Column14"></asp:GridView>
<%--Last Page Button(Not done, Datagrid vanishes on click, Last Page & Export button remain in browser view)--%>
<asp:Button ID="btnLastPage" runat="server" Text="Jump to last page" OnClick="btnLastPage_Click" />
<%--Export Button (Not done, OutOfMemoryException, need to somehow divide the workload - Stored Proc in the SQL back end behind the components maybe)--%`>`
<asp:Button ID="btnExport" runat="server" Text="Exp to Excel" OnClick="btnExport_Click"/>
</div>
</form>
</body>
</html>
Code behind
using System;
using DBComponentsLibrary;
using DBComponentsLibrary.NameDataSetTableAdapters;
using System.Web.UI.WebControls;
using System.IO;
using System.Web.UI;
using System.Drawing;
namespace Name
{
public partial class TestWebFormView : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
loadGridData();
}
private void loadGridData()
{
NameTableAdapter TA = new NameTableAdapter();
NameDataSet rds = new NameDataSet();
NameDataSet.NameDataTable Rdt = new NameDataSet.NameDataTable();
TA.Fill(Rdt);
GridView.DataSource = Rdt;
GridView.DataBind();
GridView.Rows[0].Cells[0].Visible = true;
}
protected void GridView_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
GridView.PageIndex = e.NewPageIndex;
Page.DataBind();
}
protected void btnLastPage_Click(object sender, EventArgs e)
{
int myNewIndex = GridView.PageCount - 1;
if (myNewIndex != null && myNewIndex != -1 && myNewIndex < GridView.PageCount)
{
GridView.PageIndex = myNewIndex;
}
}
protected void btnExport_Click(object sender, EventArgs e)
{
}
// //Response.Buffer = true;
// //Response.Charset = "";
// //Response.BinaryWrite(Bytes);
// Response.ClearHeaders();
// Response.Clear();
// Response.AddHeader("content-disposition", "attachment;filename=*.xls");
// Response.ContentType = "application/vnd.ms-excel";
// Response.End();
// using (StringWriter sw = new StringWriter())
// {
// HtmlTextWriter hw = new HtmlTextWriter(sw);
// //To Export all pages
// //GridView.AllowPaging = true;
// this.DataBind();
// //this.BindGrid();
// GridView.HeaderRow.BackColor = Color.White;
// foreach (TableCell cell in GridView.HeaderRow.Cells)
// {
// cell.BackColor = GridView.HeaderStyle.BackColor;
// }
// foreach (GridViewRow row in GridView.Rows)
// {
// row.BackColor = Color.White;
// foreach (TableCell cell in row.Cells)
// {
// if (row.RowIndex % 2 == 0)
// {
// cell.BackColor = GridView.AlternatingRowStyle.BackColor;
// }
// else
// {
// cell.BackColor = GridView.RowStyle.BackColor;
// }
// cell.CssClass = "textmode";
// }
// }
// GridView.RenderControl(hw);
// //style to format numbers to string
// string style = #"<style> .textmode { } </style>";
// Response.Write(style);
// Response.Output.Write(sw.ToString());
// Response.Flush();
// Response.End();
// }
//}
}
}
Edit 2016-02-17 : Edited & Cleaned up code. Still have some bugs I am trying to fix. But development is going forward. If I get stuck on something specific I will make a new post. Thanks again!
The problem is that you're setting the page number to the highest possible number representable with an In32 type.
protected void btnLastPage_Click(object sender, EventArgs e)
{
GridView.PageIndex = Int32.MaxValue;
DataBind();
}
That should be
protected void btnLastPage_Click(object sender, EventArgs e)
{
GridView.PageIndex = GridView.PageCount - 1;
DataBind();
}
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 can't figure out how to programmatically add a GridView with buttons to an UpdatePanel.
I can do it with simple controls such as buttons and labels, but when I try to add a GridView with buttons a full Postback() occurs.
<%# Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
protected override void OnInit(EventArgs e)
{
UpdatePanel up1 = new UpdatePanel();
up1.ID = "UpdatePanel1";
Button button1 = new Button();
button1.ID = "Button1";
button1.Text = "Submit";
button1.Click += new EventHandler(Button_Click);
Label label1 = new Label();
label1.ID = "Label1";
label1.Text = "A full page postback occurred.";
GridView gv1 = new GridView();
//Where the xml gets bonded to the data grind
XmlDataSource xds = new XmlDataSource();
xds.Data = xml;
xds.DataBind();
xds.EnableCaching = false;
gv1.DataSource = xds;
createButton(gv1, up1);
gv1.RowCommand += new GridViewCommandEventHandler(CustomersGridView_RowCommand);
gv1.DataBind();
up1.ChildrenAsTriggers = true;
up1.ContentTemplateContainer.Controls.Add(button1);
up1.ContentTemplateContainer.Controls.Add(label1);
up1.ContentTemplateContainer.Controls.Add(gv1);
Page.Form.Controls.Add(up1);
}
protected void Page_Load(object sender, EventArgs e)
{
}
public void CustomersGridView_RowCommand(Object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "buttonClicked")
{
int index = Convert.ToInt32(e.CommandArgument);
}
}
void createButton(GridView g)
{
ButtonField tea = new ButtonField();
tea.ButtonType = ButtonType.Image;
tea.ImageUrl = "~/checkdailyinventory.bmp";
tea.CommandName = "buttonClicked";
tea.HeaderText = "space";
g.Columns.Add(tea);
}
protected void Button_Click(object sender, EventArgs e)
{
((Label)Page.FindControl("Label1")).Text = "Panel refreshed at " +
DateTime.Now.ToString();
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>UpdatePanel Constructor Example</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Button ID="Button2" runat="server" Text="Button" />
<asp:ScriptManager ID="ScriptManager1" runat="server" />
</div>
</form>
</body>
</html>
So how do you add a gridview with buttons programmatically to an UpdatePanel without causing a full PostBack() if the GridView is clicked?
Edit: Other things I have tried
void gv1_RowDataBound(object sender, GridViewRowEventArgs e)
{
AsyncPostBackTrigger t = new AsyncPostBackTrigger();
t.ControlID = e.Row.Cells[0].ClientID;
t.EventName = "blah";
up1.Triggers.Add(t);
}
Well according to:
And I don't mind having the update panel created at the design time. I just need to be able to add stuff (like tables that contain gridviews that contain buttons into it) programmatically and then be able to do a partial postback
Basically I used your code with small changes:
Removed the binding from the Init event and I execute it in the Load event
The UpdatePanel is created at design time with a nested panel, and you simply add your dynamic controls to that panel
This code will do it (it works on my environment):
ASPX
<asp:ScriptManager runat="server" />
<asp:UpdatePanel runat="server">
<ContentTemplate>
<asp:Panel runat="server" ID="myPanel">
</asp:Panel>
<br />
<asp:Label runat="server" ID="lblMessage"></asp:Label>
</ContentTemplate>
</asp:UpdatePanel>
Code behind
protected void Page_Init(object sender, EventArgs e)
{
Button button1 = new Button();
button1.ID = "Button1";
button1.Text = "Submit";
button1.Click += new EventHandler(Button_Click);
Label label1 = new Label();
label1.ID = "Label1";
label1.Text = "A full page postback occurred.";
var s1 = Builder<Product>.CreateListOfSize(15).Build();
GridView gv1 = new GridView();
gv1.DataSource = s1;
createButton(gv1);
gv1.RowCommand += new GridViewCommandEventHandler(CustomersGridView_RowCommand);
this.myPanel.Controls.Add(button1);
this.myPanel.Controls.Add(label1);
this.myPanel.Controls.Add(gv1);
}
void createButton(GridView g)
{
ButtonField tea = new ButtonField();
tea.ButtonType = ButtonType.Image;
tea.ImageUrl = "~/checkdailyinventory.bmp";
tea.CommandName = "buttonClicked";
tea.HeaderText = "space";
g.Columns.Add(tea);
}
protected void Button_Click(object sender, EventArgs e)
{
((Label)Page.FindControl("Label1")).Text = "Panel refreshed at " +
DateTime.Now.ToString();
}
protected void Page_Load(object sender, EventArgs e)
{
this.DataBind();
}
public void CustomersGridView_RowCommand(Object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "buttonClicked")
{
//int index = Convert.ToInt32(e.CommandArgument);
this.lblMessage.Text = DateTime.Now.ToString();
}
}
Output
Couldn't you just put the GridView in there at design time and just hide it by setting Visible=false?
If you don't know how many gridviews you need to repeat then you could wrap the GridView in a ListView. The concept is introduced here:
http://mattberseth.com/blog/2008/01/building_a_grouping_grid_with.html
This might not be the perfect solution I just thought I would offer it seeing as there is a bounty I assume you have hit a brick wall so far.