GridView RowCommand Events not firing when button created with an external class - c#

Ok The problem is I have a grid that I need to have paging on it with pages shown as numbers
I want to add two link button to the paging section to alow user to navigate to next page prev page
Here is my code
protected void CustomerGridView_RowCreated(object sender, GridViewRowEventArgs e)
{
var grid = sender as GridView
if (e.Row.RowType == DataControlRowType.Pager)
{
var prvLink = new LinkButton();
prvLink.Text = "<";
prvLink.CommandName = "Page";
prvLink.CommandArgument = "Prev";
prvLink.EnableViewState = true;
var nextLink = new LinkButton();
nextLink.Text = ">";
nextLink.CommandName = "Page";
nextLink.CommandArgument = "Next";
nextLink.EnableViewState = true;
var prvCell = new TableCell();
var nextCell = new TableCell();
prvCell.Controls.Add(prvLink);
nextCell.Controls.Add(nextLink);
Table pagerTable = e.Row.Controls[0].Controls[0] as Table;
TableRow row = pagerTable.Rows[0];
row.Cells.AddAt(0, prvCell);
row.Cells.AddAt(row.Cells.Count, nextCell);
if (grid.PageIndex == 0)
{
prvCell.Enabled = false;
}
if (grid.PageIndex == grid.PageCount - 1)
{
nextCell.Enabled = false;
}
}
}
its perfectly working and users are able to navigate back and forward (and I can see grid RowCommand event getting fired)
The problem is I do not want to put the code inside my page (to make my page tiny and put the responsibility to an other class )
here is my class
public class GridStyler
{
private GridView _grid;
public GridStyler(GridView grid)
{
_grid = grid;
}
public void AddNextPreviousOnPager()
{
_grid.RowCreated += _grid_RowCreated;
}
void _grid_RowCreated(object sender, GridViewRowEventArgs e)
{
var grid = sender as GridView;
if (e.Row.RowType == DataControlRowType.Pager)
{
var prvLink = new LinkButton();
prvLink.Text = "<";
prvLink.CommandName = "Page";
prvLink.CommandArgument = "Prev";
prvLink.EnableViewState = true;
var nextLink = new LinkButton();
nextLink.Text = ">";
nextLink.CommandName = "Page";
nextLink.CommandArgument = "Next";
nextLink.EnableViewState = true;
var prvCell = new TableCell();
var nextCell = new TableCell();
prvCell.Controls.Add(prvLink);
nextCell.Controls.Add(nextLink);
Table pagerTable = e.Row.Controls[0].Controls[0] as Table;
TableRow row = pagerTable.Rows[0];
row.Cells.AddAt(0, prvCell);
row.Cells.AddAt(row.Cells.Count, nextCell);
if (grid.PageIndex == 0)
{
prvCell.Enabled = false;
}
if (grid.PageIndex == grid.PageCount - 1)
{
nextCell.Enabled = false;
}
}
}
}
then I should be able to call a code like that in my page load and it should create the link buttons and response to click of them
var g = new GridStyler(CustomerGridView);
g.AddNextPreviousOnPager();
what happens is the link buttons are created just fine but when user clicks them page get refreshed but RowCommand never get fired (they get fired of course when user clicks other buttons but not this two dynamically created buttons)
Any suggestion is really appreciated

Related

Creating Dynamic controls when changing the dropdown list items. - c#

I have to show a ModalPopupExtender when changing the items of dropdownlist. The controls showing inside the ModalPopupExtender are dynamic controls including buttons. To fire the button click event for this dynamic buttons, I have introduced view state in the code.
Now when changing the item of dropdown list, ModalPopupExtender will come for first item correctly. And then, when changing the item, it throws error like below. How can I clear the previous dynamic controls when changing the dropdown list items?
Multiple controls with the same ID 'lbl1' were found. FindControl requires that controls have unique IDs.
protected async void Page_Load(object sender, EventArgs e)
{
if (ddl_Forms.SelectedItem.Value != "-1")
if (ViewState["viewstate_dynamic"] != null)
CreateDynamicControls();
}
protected void ddl_Forms_SelectedIndexChanged(object sender, EventArgs e)
{
CreateDynamicControls();
}
private async void CreateDynamicControls()
{
if (ddl_Forms.SelectedItem.Value != "-1")
{
url = baseUrl + "GetStructureJson?form_id=" + ddl_Forms.SelectedItem.Value.ToString();
using (var objClient = new HttpClient())
{
objClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + objVariables.login_token);
using (var response = await objClient.GetAsync(url))
{
if ((int)response.StatusCode == 401)//unauthorised or token expired
{
Response.Redirect("Default.aspx");
}
if (response.IsSuccessStatusCode)
{
var jsonString = await response.Content.ReadAsStringAsync();
JavaScriptSerializer j = new JavaScriptSerializer();
object a = j.Deserialize(jsonString, typeof(object));
dict_values = JsonConvert.DeserializeObject<Dictionary<string, string>>(a.ToString());
int flag = 0;
foreach (KeyValuePair<string, string> entry in dict_values)
{
flag++;
TableRow row = new TableRow();
TableCell cell1 = new TableCell();
Label lbl = new Label();
lbl.ID = "lbl" + flag;
lbl.Text = entry.Key;
cell1.Controls.Add(lbl);
row.Cells.Add(cell1);
tbl_forms.Rows.Add(row);
}
TableRow row3 = new TableRow();
TableCell cell3 = new TableCell();
Button btn = new Button();
btn.ID = "btnSubmit2";
btn.Text = "Submit";
btn.Click += new System.EventHandler(this.ButtonsubmitForm2_Click);
btn.CssClass = "button_green";
cell3.Controls.Add(btn);
Button btn2 = new Button();
btn2.ID = "btnCancel2";
btn2.Text = "Cancel";
btn2.Click += new EventHandler(btn_Cancel_allocate2_Click);
btn2.Style.Add("margin-left", "20px");
cell3.Controls.Add(btn2);
row3.Cells.Add(cell3);
tbl_forms.Rows.Add(row3);
**ViewState.Add("viewstate_dynamic", true);**
mp2.Show(); //modalpopuextender
}
}
}
}
}

FindControl() returns null when searching for dynamic control

In my requirement I am creating dynamic controls by two events
Dropdownlist OnSelectedIndexChanged event
Onclick button event
In OnSelectedIndexChanged event i have created number of dynamic textbox.
Here I have create two dynamic textboxes.
I am getting all enquiry product list based on enquiry number from the dynamic textboxes on button click event
All are dynamic controls
While saving the productlist the checkbox control return null value
protected void ddlenqChaged(object sender, EventArgs e)
{
getenqTextbox();
}
protected void btnSearchClick(object sender, EventArgs e)
{
tblbill.Visible = true;
if (Convert.ToString(ViewState["Generated"]) != "true")
{
CreateDynamicControls();
ViewState["Generated"] = "true";
}
}
protected void getenqTextbox()
{
enqPanel.Controls.Clear();
if (Convert.ToInt32(ddlNoofEnq.SelectedValue) > 0)
{
for (int i = 1; i <= Convert.ToInt32(ddlNoofEnq.SelectedValue); i++)
{
TextBox _txtCode = new TextBox();
_txtCode.ID = "txtEnqqNo" + i;
_txtCode.Attributes.Add("ClientIDMode", "Static");
_txtCode.Width = 75;
_txtCode.CssClass = "AtCompleteByEnq";
enqPanel.Controls.Add(_txtCode);
}
}
}
protected void CreateDynamicControls()
{
int m = 1;
//int encount = click.buttonclick;
if (Convert.ToInt32(ddlNoofEnq.SelectedValue) > 0)
{
Table tbldynamic = new Table();
for (int k = 1; k <= Convert.ToInt32(ddlNoofEnq.SelectedValue); k++)
{
Panel1.Controls.Clear();
TextBox tb = (TextBox)enqPanel.FindControl("txtEnqqNo" + k);
if (tb != null)
{
if (!String.IsNullOrEmpty(tb.Text))
{
List<Enquiry_ProductListBLL> objlst = Enquiry_ProductListBLL.GetEnquiry_ProductListBLLs(tb.Text);
foreach (Enquiry_ProductListBLL item in objlst)
{
TableRow tr = new TableRow();
TableCell tc = new TableCell();
TableCell tc1 = new TableCell();
TableCell tc2 = new TableCell();
TableCell tc3 = new TableCell();
TableCell tc4 = new TableCell();
TableCell tc5 = new TableCell();
TableCell tc6 = new TableCell();
Master_ProductBLL objpdt = Master_ProductBLL.GetMaster_ProductBLL(item.ProductId);
CheckBox _chkRowNo = new CheckBox();
_chkRowNo.ID = "chkRowNo" + m;
_chkRowNo.Text = m.ToString();
_chkRowNo.Attributes.Add("ClientIDMode", "Static");
_chkRowNo.Attributes.Add("onclick", "getEnable(this);");
_chkRowNo.Checked = true;
TextBox _txtCode = new TextBox();
_txtCode.ID = "txtCodeRow" + m;
_txtCode.Attributes.Add("ClientIDMode", "Static");
_txtCode.Enabled = false;
_txtCode.Width = 75;
_txtCode.Attributes.Add("autocomplete", "off");
_txtCode.Text = objpdt.Code;
HiddenField _hdnPdtId = new HiddenField();
_hdnPdtId.ID = "hdnPdtId" + m;
_hdnPdtId.Value = item.ProductId.ToString();
HiddenField _hdEnqNo = new HiddenField();
_hdEnqNo.ID = "hdEnqNo" + m;
_hdEnqNo.Value = item.EnqNo;
_hdnPdtId.Value = item.ProductId.ToString();
TextBox _txtPdtName = new TextBox();
_txtPdtName.ID = "txtPdtNameRow" + m;
_txtPdtName.Attributes.Add("ClientIDMode", "Static");
_txtPdtName.Enabled = false;
_txtPdtName.Width = 150;
_txtPdtName.CssClass = "AtCompleteByName";
_txtPdtName.Text = objpdt.Name;
TextBox _txtQty = new TextBox();
_txtQty.ID = "txtQtyRow" + m;
_txtQty.Width = 80;
_txtQty.MaxLength = 8;
_txtQty.Attributes.Add("ClientIDMode", "Static");
//_txtQty.Attributes.Add("onblur", "GetTotal(this)");
//_txtQty.Enabled = false;
_txtQty.Text = item.Count.ToString();
DropDownList ddlUnits = new DropDownList();
ddlUnits.ID = "ddlUnits" + m;
ddlUnits.CssClass = "dropdowncss";
ddlUnits.Width = 100;
Bindings.BindUnitName(ddlUnits);
ddlUnits.Items.FindByText(item.PP).Selected = true;
tc.Controls.Add(_chkRowNo);
tc1.Controls.Add(_txtCode);
tc2.Controls.Add(_txtPdtName);
tc2.Controls.Add(_hdnPdtId);
tc2.Controls.Add(_hdEnqNo);
tc3.Controls.Add(_txtBrand);
tc4.Controls.Add(_txtThickness);
tc5.Controls.Add(ddlUnits);
tc6.Controls.Add(_txtQty);
tc.Attributes.Add("Width", "50px");
tr.Attributes.Add("id", "Rowid" + m);
tr.Attributes.Add("class", "paidRw");
tr.Cells.Add(tc);
tr.Cells.Add(tc1);
tr.Cells.Add(tc2);
tr.Cells.Add(tc3);
tr.Cells.Add(tc4);
tr.Cells.Add(tc5);
tr.Cells.Add(tc6);
tbldynamic.Rows.Add(tr);
m++;
}
}
}
}
Panel1.Controls.Add(tbldynamic);
}
}
Here I have override OnLoad event
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
CreateDynamicControls();
getenqTextbox();
}
My problem is i cannot find controls from Panel1
CheckBox chk = (CheckBox)Panel1.FindControl(chkId);
if (chk != null)
{
if (chk.Checked == true)
{
//my process
}
}
FindControl returns null value.
Here I have create dynamic controls two times.
I cannot have any problem with enquiry textbox, it was created first, but the second time button click event controls are return null.
FindControl does not walk the hierarchy.
See doc Control.FindControl()
This method will find a control only if the control is directly contained by the specified container; that is, the method does not search throughout a hierarchy of controls within controls.
Since your CheckBox is not a first-level child of the Panel, it cannot be retrieved this way. If you need a generic solution, I suggest to implement a recursive FindControl.

Click event of dynamically created Button not firing

I'm creating dynamically generated buttons, and when I click on the button, the Add_Click method doesn't get fired up.
Here is a sample from my code:
protected void SearchRec(object sender, EventArgs e)
{
SearchResultsPanel.Controls.Clear();
string text_to_search = SearchTB.Text;
Friends RecToSearch = new Friends();
List<Friends> ListNFU = DBS.getNonFriendUsers(User.Identity.Name.ToString(), text_to_search);
if (ListNFU.Count != 0)
{
foreach (Friends NFRIndex in ListNFU)
{
string _FriendsOutput = FR_output(NFRIndex);
HyperLink RecHyperLink = new HyperLink();
RecHyperLink.Text = _FriendsOutput;
RecHyperLink.CssClass = "HyperLinkFriends";
RecHyperLink.ID = NFRIndex.UdName;
SearchResultsPanel.Controls.Add(new LiteralControl("<div style='height:32px'>"));
SearchResultsPanel.Controls.Add(RecHyperLink);
Button addUser = new Button();
addUser.CssClass = "ApproveBTN";
addUser.Text = "send";
addUser.Click += new EventHandler(Add_Click);
addUser.ID = NFRIndex.UdName + "3";
SearchResultsPanel.Controls.Add(addUser);
}
}
else
{
Label NoResultsLabel = new Label();
NoResultsLabel.Text = "Nothing is found";
SearchResultsPanel.Controls.Add(NoResultsLabel);
}
SearchResultsPanel.Controls.Add(new LiteralControl("</div>"));
}
private void Add_Click(object sender, EventArgs e)
{
Button btn = (Button)sender;
string _tempID = btn.ID;
string id = _tempID.Substring(0, _tempID.LastIndexOf('3'));
DateTime cdate = new DateTime();
cdate = DateTime.Now;
DBS.AddFriend(User.Identity.Name, id, cdate);
btn.Visible = false;
btn.NamingContainer.FindControl(id).Visible = false;
}
Note: I did something very similar on page_load and it does work.
That is because when the page is reloaded, the control is most probably not recreated. That means that the event won't fire indeed.
You need to place this kind of code in the Page_Load so it gets recreated at postback.

OnTextChanged event not firing inside UpdatePanel - both created dynamically

What I am trying to do is to populate column of GridView with textboxes and to execute some function OnTextChanged.
This is my code:
if (e.Row.RowType == DataControlRowType.DataRow)
{
UpdatePanel UP_AmountToBuy = new UpdatePanel();
UP_AmountToBuy.ContentTemplateContainer.Controls.Clear();
UP_AmountToBuy.Triggers.Clear();
UP_AmountToBuy.UpdateMode = UpdatePanelUpdateMode.Conditional;
UP_AmountToBuy.ChildrenAsTriggers = false;
UP_AmountToBuy.Attributes["runat"] = "server";
//Create and add TextBox
TextBox TB_AmountToBuy = new TextBox();
TB_AmountToBuy.Text = "0";
TB_AmountToBuy.TextChanged += new EventHandler(TB_AmountToBuy_TextChanged);
TB_AmountToBuy.Attributes["OnTextChanged"] = "TB_AmountToBuy_TextChanged";
TB_AmountToBuy.Attributes["runat"] = "server";
TB_AmountToBuy.AutoPostBack = true;
TB_AmountToBuy.ViewStateMode = System.Web.UI.ViewStateMode.Enabled;
TB_AmountToBuy.ID = "buyID" + count;
UP_AmountToBuy.ContentTemplateContainer.Controls.Add(TB_AmountToBuy);
//Create and add AsyncPostBackTrigger
AsyncPostBackTrigger APBT_trig = new AsyncPostBackTrigger();
APBT_trig.EventName = "TextChanged";
APBT_trig.ControlID = TB_AmountToBuy.ID;
UP_AmountToBuy.Triggers.Add(APBT_trig);
Label newLBL = new Label();
newLBL.Text = "123";
newLBL.Attributes["runat"] = "server";
UP_AmountToBuy.ContentTemplateContainer.Controls.Add(newLBL);
e.Row.Cells[5].Controls.Add(UP_AmountToBuy);
count++;
}
}
public void TB_AmountToBuy_TextChanged(object sender, EventArgs e)
{
((sender as TextBox).Parent.Controls[1] as Label).Text = (sender as TextBox).Text;
}
The problem is, that event OnTextChanged never fired...
Dynamically generated controls needs to be created every time in page load in order to restore their view state ,fire events and get value from them.Like this
public partial class _Default : Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
var dt = new System.Data.DataTable();
dt.Columns.Add("Col1");
dt.Rows.Add("Hi");
GridView1.DataSource = dt;
GridView1.DataBind();
}
CreateDynamicControles();
}
public void CreateDynamicControles()
{
var count = 0;
foreach (GridViewRow row in GridView1.Rows)
{
if (row.RowType == DataControlRowType.DataRow)
{
UpdatePanel UP_AmountToBuy = new UpdatePanel();
UP_AmountToBuy.ContentTemplateContainer.Controls.Clear();
UP_AmountToBuy.Triggers.Clear();
UP_AmountToBuy.UpdateMode = UpdatePanelUpdateMode.Conditional;
UP_AmountToBuy.ChildrenAsTriggers = false;
UP_AmountToBuy.Attributes["runat"] = "server";
//Create and add TextBox
TextBox TB_AmountToBuy = new TextBox();
TB_AmountToBuy.Text = "0";
TB_AmountToBuy.TextChanged += new EventHandler(TB_AmountToBuy_TextChanged);
TB_AmountToBuy.Attributes["OnTextChanged"] = "TB_AmountToBuy_TextChanged";
TB_AmountToBuy.Attributes["runat"] = "server";
TB_AmountToBuy.AutoPostBack = true;
TB_AmountToBuy.ViewStateMode = System.Web.UI.ViewStateMode.Enabled;
TB_AmountToBuy.ID = "buyID" + count;
UP_AmountToBuy.ContentTemplateContainer.Controls.Add(TB_AmountToBuy);
//Create and add AsyncPostBackTrigger
AsyncPostBackTrigger APBT_trig = new AsyncPostBackTrigger();
APBT_trig.EventName = "TextChanged";
APBT_trig.ControlID = TB_AmountToBuy.ID;
UP_AmountToBuy.Triggers.Add(APBT_trig);
Label newLBL = new Label();
newLBL.Text = "123";
newLBL.Attributes["runat"] = "server";
UP_AmountToBuy.ContentTemplateContainer.Controls.Add(newLBL);
row.Cells[0].Controls.Add(UP_AmountToBuy);
count++;
}
}
}
public void TB_AmountToBuy_TextChanged(object sender, EventArgs e)
{
((sender as TextBox).Parent.Controls[1] as Label).Text = (sender as TextBox).Text;
}
}
Try this, since you are using UpdatePanel. So use following property.
Set property:
EnableViewstate="True"

Creating dynamic controls on Page_LoadComplete

I have three drop down lists and depending on the values selected in the lists I create dynamic controls accordingly. Everything displays properly but when I click on the dynamically created button the events are not firing. I am using the Page_LoadComplete to create the dynamic controls because I need to the values from the DDL's. Is this the reason for my button events not firing?
protected void Page_LoadComplete(object sender, EventArgs e)
{
queries = new clsFormQueries();
if (HttpContext.Current.User.IsInRole("Admin"))
{
if (!Page.IsPostBack)
{
List<Sport> sports = ComboBoxOptions.getSports();
DropDownList temp = (DropDownList)loginView2.FindControl("Sport");
temp.DataSource = sports;
temp.DataTextField = "Name";
temp.DataValueField = "id";
temp.DataBind();
DropDownList teamsDD = (DropDownList)loginView2.FindControl("Team");
List<Team> teamsList = ComboBoxOptions.getTeamsBySportId(Convert.ToInt32(temp.SelectedValue));
teamsDD.DataSource = teamsList;
teamsDD.DataTextField = "fullName";
teamsDD.DataValueField = "teamId";
teamsDD.DataBind();
DropDownList existingPlayers = (DropDownList)loginView2.FindControl("ExistingPlayers");
List<Player> players = ComboBoxOptions.getPlayersBySport(Convert.ToInt32(temp.SelectedValue), Convert.ToInt32(teamsDD.SelectedValue));
existingPlayers.DataSource = players;
existingPlayers.DataTextField = "fullName";
existingPlayers.DataValueField = "playerid";
existingPlayers.DataBind();
//if (existingPlayers.SelectedValue != "" && temp.SelectedValue != "")
//{
// DataTable updates = queries.GetPlayerUpdate(Convert.ToInt32(existingPlayers.SelectedValue), Convert.ToInt32(temp.SelectedValue));
// if (updates.Rows.Count > 0)
// CreateUpdatesHTML(updates);
//}
}
DropDownList temp2 = (DropDownList)loginView2.FindControl("Sport");
DropDownList existingPlayers2 = (DropDownList)loginView2.FindControl("ExistingPlayers");
if (existingPlayers2.SelectedValue != "" && temp2.SelectedValue != "")
{
DataTable updates = queries.GetPlayerUpdate(Convert.ToInt32(existingPlayers2.SelectedValue), Convert.ToInt32(temp2.SelectedValue));
if (updates.Rows.Count > 0)
CreateUpdatesHTML(updates);
}
}
}
private void CreateUpdatesHTML(DataTable updates)
{
foreach (DataRow update in updates.Rows)
{
int playerUpdateId = (int)update["playerUpdateId"];
string updateText = update["PlayerUpdate"].ToString();
TextBox tb = new TextBox();
tb.ID = "UpdateText" + playerUpdateId;
tb.TextMode = TextBoxMode.MultiLine;
tb.Rows = 5;
tb.Text = updateText;
tb.CssClass = "span5";
Button btnDelete = new Button();
btnDelete.Click += new EventHandler(btnDelete_Click);
btnDelete.ID = "Delete"+playerUpdateId.ToString();
btnDelete.Text = "Delete";
btnDelete.CssClass = "btn btn-info";
Button btnUpdate = new Button();
btnUpdate.Click += new EventHandler(btnUpdate_Click);
btnUpdate.ID = "Update"+playerUpdateId.ToString();
btnUpdate.Text = "Update";
btnUpdate.CssClass = "btn btn-info";
HtmlGenericControl div2 = new HtmlGenericControl("div");
div2.Attributes.Add("class", "pull-right span5");
div2.Controls.Add(btnDelete);
div2.Controls.Add(btnUpdate);
HtmlGenericControl hr = new HtmlGenericControl("hr");
HtmlGenericControl br = new HtmlGenericControl("br");
existingUpdates.Controls.Add(tb);
existingUpdates.Controls.Add(div2);
existingUpdates.Controls.Add(br);
existingUpdates.Controls.Add(hr);
}
}
My guess is that since you have wrapped the logic for your Page_LoadComplete event inside of a n if(!Page.IsPostBack), since the click of the button causes a postback, your dynamically created controls are not recreated properly (read: no click event handling is wired up). You need to have logic on every invocation of Page_LoadComplete (non-postback or postback) that recreates the dynamic controls and wires up their events.

Categories

Resources