Cannot populate a DropDownList in EditItemTemplate using OnRowCommand - c#

This is my code behind code. I want to populate the DropDownList once the user clicked edit but the DropDownList I'm getting is null. Why?
protected void SupportSchedule_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "EditRow")
{
int rowIndex = ((GridViewRow)((ImageButton) e.CommandSource).NamingContainer).RowIndex;
GridViewRow row = (GridViewRow)(((ImageButton) e.CommandSource).NamingContainer);
SupportScheduleTable.EditIndex = rowIndex;
shift.Enabled = true;
resourcedate.Enabled = true;
ListItemCollection c = db.fillList();
DropDownList ddl1 = row.FindControl("ddlshiftmanager") as DropDownList;
DropDownList ddl2 = row.FindControl("ddldispatcherone") as DropDownList;
DropDownList ddl3 = row.FindControl("ddldispatchertwo") as DropDownList;
if (c != null && ddl1 != null)
{
ddl1.DataSource = c;
ddl2.DataSource = c;
ddl3.DataSource = c;
ddl1.DataBind();
ddl2.DataBind();
ddl3.DataBind();
}
getSupportSchedule();
}
else if (e.CommandName == "CancelUpdate")
{
//some codes here
} else if (e.CommandName == "UpdateRow")
{
//some codes here
}
}
//asp code
<asp:GridView ID="SupportScheduleTable" AutoGenerateColumns="False" Width="100%" runat="server" OnRowCommand="SupportSchedule_RowCommand">
<Columns>
<asp:TemplateField HeaderText="Shift Manager">
<EditItemTemplate>
<asp:DropDownList ID="ddlshiftmanager" runat="server" Width="99%"></asp:DropDownList>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Bind("shift_manager") %>'></asp:Label>
</ItemTemplate>
<HeaderStyle Width="32%" />
</asp:TemplateField>
<asp:TemplateField ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:ImageButton ID="lbEdit" CssClass="btn" ImageUrl="~/Files/edit.png" CommandArgument='<%# Eval("support_schedule_id") %>' CommandName="EditRow" runat="server"></asp:ImageButton>
</ItemTemplate>
<EditItemTemplate>
<asp:LinkButton ID="lbUpdate" CommandArgument='<%# Eval("support_schedule_id") %>' CommandName="UpdateRow" runat="server">Update</asp:LinkButton>
<asp:LinkButton ID="lbCancel" CommandArgument='<%# Eval("support_schedule_id") %>' CommandName="CancelUpdate" runat="server" CausesValidation="false">Cancel</asp:LinkButton>
</EditItemTemplate>
<HeaderStyle Width="2%" />
</asp:TemplateField>
//two dropdownlists before image button
</Columns>
</GridView>
I just added the ImageButton here in the recent update but this is my original code that doesn't work.

I used a SqlDataSource instead of adding the list items from the back
and this is what I used to get the selected value of the DropDownList.
else if (e.CommandName == "UpdateRow")
{
int rowIndex = ((GridViewRow)((LinkButton)e.CommandSource).NamingContainer).RowIndex;
DropDownList ddlshift = (DropDownList)SupportScheduleTable.Rows[rowIndex].FindControl("ddlshiftmanager");
DropDownList ddlone = (DropDownList)SupportScheduleTable.Rows[rowIndex].FindControl("ddldispatcherone");
DropDownList ddltwo = (DropDownList)SupportScheduleTable.Rows[rowIndex].FindControl("ddldispatchertwo");
string manager = ddlshift.SelectedValue;
string one = ddlone.SelectedValue;
string two = ddltwo.SelectedValue;
int supportID = Convert.ToInt32(e.CommandArgument);
String sh = shift.Text;
String date = resourcedate.Text;
db.updateSS(supportID, sh, manager, one, two,date);
SupportScheduleTable.EditIndex = -1;
shift.Enabled = false;
resourcedate.Enabled = false;
getSupportSchedule();
}

Your answer is a correct way to handle the issue you are seeing. But, in case you didn't figure out the actual cause...
The ImageButton you click is in your ItemTemplate. The DropDownList you want to bind is in your EditItemTemplate. lbEdit exists when you are not in edit mode but ddlshiftmanager only exists when you are.
So, the fix is to put the GridView in edit mode. Notice that this is something you actually already started to do. You need to set the EditIndex, re-bind the GridView, then get the row again. You'll then have the row in edit mode. This row should now contain ddlshiftmanager.
protected void SupportSchedule_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "EditRow")
{
int rowIndex = ((GridViewRow)((ImageButton) e.CommandSource).NamingContainer).RowIndex;
// Set the index to edit
SupportScheduleTable.EditIndex = rowIndex;
// Re-bind the GridView to put it in edit mode
SupportScheduleTable.DataSource = /* your data source */
SupportScheduleTable.DataBind();
// Get the row at the index. The row will be the
// row reflected in edit mode.
GridViewRow editRow = SupportScheduleTable.Rows[rowIndex];
// Find your DropDownLists in this edit row
DropDownList ddl1 = editRow.FindControl("ddlshiftmanager") as DropDownList;
DropDownList ddl2 = editRow.FindControl("ddldispatcherone") as DropDownList;
DropDownList ddl3 = editRow.FindControl("ddldispatchertwo") as DropDownList;
shift.Enabled = true;
resourcedate.Enabled = true;
ListItemCollection c = db.fillList();
if (c != null && ddl1 != null)
{
ddl1.DataSource = c;
ddl2.DataSource = c;
ddl3.DataSource = c;
ddl1.DataBind();
ddl2.DataBind();
ddl3.DataBind();
}
getSupportSchedule();
}
// Everything else...
}

Related

Getting gridview checked boxes

I have this template field
<asp:TemplateField ItemStyle-Width="40px">
<HeaderTemplate>
<asp:CheckBox ID="chkboxSelectAll" runat="server" AutoPostBack="true" OnCheckedChanged="chkboxSelectAll_CheckedChanged" />
</HeaderTemplate>
<ItemStyle HorizontalAlign="Center" VerticalAlign="Middle" />
<ItemTemplate>
<asp:CheckBox ID="chkEmp" runat="server"></asp:CheckBox>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField ShowHeader="False">
In the code-behind I have this code:
protected void chkboxSelectAll_CheckedChanged(object sender, EventArgs e)
{
CheckBox ChkBoxHeader = (CheckBox)grdGeral.HeaderRow.FindControl("chkboxSelectAll");
foreach (GridViewRow row in grdGeral.Rows)
{
CheckBox ChkBoxRows = (CheckBox)row.FindControl("chkEmp");
if (ChkBoxHeader.Checked == true)
{
ChkBoxRows.Checked = true;
}
else
{
ChkBoxRows.Checked = false;
}
}
}
protected void btnLista_Click(object sender, EventArgs e)
{
string strEmailTotal = "";
string strEmail = "";
foreach (GridViewRow row in grdGeral.Rows)
{
CheckBox chkBx = (CheckBox)grdGeral.FindControl("chkEmp");
if (chkBx != null)
{
if (chkBx.Checked)
{
strEmail = ((Label)grdGeral.FindControl("lblEmail")).Text;
strEmailTotal = strEmailTotal + "," + strEmail;
}
}
}
lblMail.Text = strEmailTotal ;
}
I always get a null value for the checkbox, even if I set the default value to "true" in the templatefield. Can anyone help me with this?
Thank you
In your btnLista_Click event you should use row instead grdGeral:
CheckBox chkBx = (CheckBox)row.FindControl("chkEmp");
And below this the same:
strEmail = ((Label)row.FindControl("lblEmail")).Text;
try this solution.
foreach (GridViewRow row in grdGeral.Rows)
{
CheckBox chkBx = row.FindControl("chkEmp") as CheckBox ;
}

LinkButtons inside a Grid template to increment and decrement the lables value

protected void Gridproducts_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
HyperLink hp = new HyperLink();
hp = (HyperLink)e.Row.FindControl("linkSelectprd");
var Pid = DataBinder.Eval(e.Row.DataItem, "product_id").ToString();
var Catid = Request.QueryString["Cid"].ToString();
hp.NavigateUrl = "Sales.aspx?Cid="+Catid+"&"+"Pid="+Pid;
if (!IsPostBack && Request.QueryString["Pid"] != null)
{
this is the variable in which the value of quantity increments
int i=0;
lbltotalquantity.Text = i.ToString() + 1;
}
}
}
}
I use LinkButtons inside a Grid template. I want to be able to raise events when clicking the LinkButtons the value of lable is incremented on + link and decrementd on - link button as lable contains the quantity of Products added to invoice. How can I accomplish this?
I believe this is what you want....
You don't do the increment in RowDataBound because RowDataBound trigger when you are binding the GridView
.aspx
<asp:ScriptManager ID="sm" runat="server"></asp:ScriptManager>
<asp:UpdatePanel ID="up" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:GridView ID="gv" runat="server" AutoGenerateColumns="false">
<Columns>
<asp:TemplateField HeaderText="Product">
<ItemTemplate>
<asp:Label ID="lblProduct" runat="server" Text='<%# Eval("Product") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Quantity">
<ItemTemplate>
<asp:Label ID="lblQuantity" runat="server" Text="0"></asp:Label>
<asp:LinkButton ID="lbtnPlus" runat="server" Text="+" OnClick="lbtnPlus_Click"></asp:LinkButton>
<asp:LinkButton ID="lbtnMinus" runat="server" Text="-" OnClick="lbtnMinus_Click"></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="gv" />
</Triggers>
</asp:UpdatePanel>
.cs
protected void Page_Load(object sender, EventArgs e)
{
// Check
if (!IsPostBack)
{
// Variable
string[] product = { "Dell", "Asus", "Acer", "Toshiba", "Fujishu", "VAIO" };
DataTable dt = new DataTable();
dt.Columns.Add("Product");
for (int i = 0; i < product.Length; i++)
dt.Rows.Add(product[i]);
gv.DataSource = dt;
gv.DataBind();
// Dispose
dt.Dispose();
}
}
private void DoTheMath(GridViewRow row, bool isAdd)
{
// Variable
bool isNumber = false;
int currentValue = 0;
// Find Control
Label lblQuantity = row.FindControl("lblQuantity") as Label;
// Check
if (lblQuantity != null)
{
// Check
if (lblQuantity.Text.Trim() != string.Empty)
{
isNumber = int.TryParse(lblQuantity.Text.Trim(), out currentValue);
// Check
if (isNumber)
{
// Is Add
if (isAdd)
currentValue++;
else
{
// Check cannot be less than 0
if (currentValue > 0)
currentValue--;
}
}
// Set to TextBox
lblQuantity.Text = currentValue.ToString();
}
}
}
protected void lbtnPlus_Click(object sender, EventArgs e)
{
// Get
LinkButton lbtn = sender as LinkButton;
GridViewRow row = lbtn.NamingContainer as GridViewRow;
DoTheMath(row, true);
}
protected void lbtnMinus_Click(object sender, EventArgs e)
{
// Get
LinkButton lbtn = sender as LinkButton;
GridViewRow row = lbtn.NamingContainer as GridViewRow;
DoTheMath(row, false);
}

Gridview EditItemTemplate DropDownList Get SelectedValue

In my Gridview I have the following template field:
<asp:TemplateField HeaderText="Dept Code" SortExpression="DeptCode">
<ItemTemplate>
<%# Eval("DeptCode") %>
</ItemTemplate>
<EditItemTemplate>
<asp:DropDownList ID="ddlDeptCode" runat="server"
SelectedValue='<%# Eval("DeptCode") %>'
DataSource='<%# GetAllDepartments() %>'
DataTextField="DeptCode"
DataValueField="DeptCode" />
</EditItemTemplate>
</asp:TemplateField>
This works great when I click Edit on a row it populates the DropDownList with all values and selects the correct value for that row.
However, when I try to update the row: OnRowUpdating="UpdateRow"
protected void UpdateRow(object sender, GridViewUpdateEventArgs e)
{
GridViewRow row = UserGV.Rows[e.RowIndex];
DropDownList ddl = row.FindControl("ddlDeptCode") as DropDownList;
string deptCode = ddl.SelectedValue;
}
It finds the DropDownList control but the SelectedValue is always an empty string.
I need access to the selected value to save to the database.
Any ideas as to how I can get the SelectedValue of a DropDownList in a Gridview in code behind?
Edit:
You can also populate the DropDownList and SelectedValue from the code behind:
protected void gv_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
if ((e.Row.RowState & DataControlRowState.Edit) > 0)
{
var deptMgr = new DepartmentMgr();
List<Department> departments = deptMgr.GetAllDepartments();
DropDownList ddList = (DropDownList)e.Row.FindControl("ddlDeptCode");
ddList.DataSource = departments;
ddList.DataTextField = "DeptCode";
ddList.DataValueField = "DeptCode";
ddList.DataBind();
string userDeptCode = DataBinder.Eval(e.Row.DataItem, "DeptCode").ToString();
ddList.SelectedItem.Text = userDeptCode;
ddList.SelectedValue = userDeptCode;
}
}
}
I was using a bit of a hack to get a second header for the table title when binding the gridview:
GridViewRow row = new GridViewRow(0, -1, DataControlRowType.Header, DataControlRowState.Normal);
TableCell th = new TableHeaderCell();
th.HorizontalAlign = HorizontalAlign.Center;
th.ColumnSpan = UserGV.Columns.Count;
th.BackColor = Color.SteelBlue;
th.ForeColor = Color.White;
th.Font.Bold = true;
th.Text = "Manage Users";
row.Cells.Add(th);
InnerTable.Rows.AddAt(0, row);
I don't completely understand how this was interfering with getting the SelectedValue of a DropDownList control but as soon as I commented that out it started working.
For those interested I got the second header working with this using a different approach:
In the .aspx file I added this to the Gridview:
OnRowCreated="CreateRow"
And in the code behind I added the following method:
protected void CreateRow(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.Header)
{
GridView gridView = (GridView)sender;
GridViewRow row = new GridViewRow(1, 0, DataControlRowType.Header, DataControlRowState.Normal);
TableCell th = new TableHeaderCell();
th.HorizontalAlign = HorizontalAlign.Center;
th.ColumnSpan = UserGV.Columns.Count;
th.ForeColor = Color.White;
th.BackColor = Color.SteelBlue;
th.Font.Bold = true;
th.Text = "Manage Users";
row.Cells.Add(th);
gridView.Controls[0].Controls.AddAt(0, row);
}
}
Everything is working correctly now.
In the edit template, set the selectedvalue from the data bindings, then you will get the correct selected value instead of a null.
SelectedValue='<%# Bind("DeptCode") %>'

Getting row index of checked row

I am trying to do when the checkbox column in my gridview is marked, I get the row index. My gridview is in a repeater and when I setup the gridview, I put a DataKeyNames:
<asp:Repeater ID="Repeater1" runat="server" OnItemDataBound="Repeater1_ItemDataBound">
<ItemTemplate>
<asp:Panel ID="pBody1" runat="server" CssClass="cpBody">
<asp:Label ID="lblBodyText1" runat="server" />
<!-- Grid view to show products based on each category -->
<asp:GridView ID="gvProduct" runat="server" AutoGenerateColumns="False" Width="998px" CellPadding="4" ForeColor="#333333" GridLines="None" ShowHeader="False" DataKeyNames="id">
<AlternatingRowStyle BackColor="White" ForeColor="#284775" />
<Columns>
<asp:TemplateField ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:CheckBox ID="cbCheckRow" runat="server" />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="name" HeaderText="Name" ItemStyle-Width="600px" />
<asp:BoundField DataField="categoryName" HeaderText="Category" />
<asp:TemplateField HeaderText="Quantity" ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:TextBox ID="tbQuantity" runat="server" Width="60" Text='<%# DataBinder.Eval(Container.DataItem, "inventoryQuantity") %>'/>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</asp:Panel>
<asp:CollapsiblePanelExtender ID="cpe1" runat="server" TargetControlID="pBody1" CollapseControlID="pHeader1"
ExpandControlID="pHeader1" Collapsed="true" ImageControlID="imgArrows1"
CollapsedImage="~/Images/downarrow.jpg"
ExpandedImage="~/Images/uparrow.jpg" TextLabelID="lblHeaderText1" CollapsedText="Show"
ExpandedText="Hide" CollapsedSize="0"
ScrollContents="false">
</asp:CollapsiblePanelExtender>
</ItemTemplate>
</asp:Repeater>
<asp:LinkButton ID="lbnConfirm" runat="server" class="btn dark" style="float: right" OnClick="lbnConfirm_Click">Confirm</asp:LinkButton>
When my lbnConfirm is onclick, I perform this to get the row index and store them into a list:
protected void lbnConfirm_Click(object sender, EventArgs e)
{
GridView gv = (GridView)Repeater1.FindControl("gvProduct") as GridView;
foreach (GridViewRow gr in gv.Rows)
{
CheckBox cb = (CheckBox)gr.Cells[0].FindControl("cbCheckRow");
if (cb.Checked)
{
GridViewRow row = gv.SelectedRow;
string prodID = this.gv.DataKeys[row].Value.ToString();
List<DistributionStandardPackingUnitItems> distSPUList = new List<DistributionStandardPackingUnitItems>();
//Store the prodIDs into list
}
}
}
When I run the page, it told me object reference is not set to an instance at this line:
foreach (GridViewRow gr in gv.Rows)
Also the gv of this line:
string prodID = this.gv.DataKeys[row].Value.ToString();
told me that the gv does not contain a definition of missing reference. I thought I declared at the code above?
Edited Portion:
protected void lbnConfirm_Click(object sender, EventArgs e)
{
foreach (RepeaterItem item in Repeater1.Items)
{
if (item.ItemType == ListItemType.Item || item.ItemType == ListItemType.AlternatingItem)
{
Panel pnl = item.FindControl("pBody1") as Panel;
GridView gv = pnl.FindControl("gvProduct") as GridView;
foreach (GridViewRow gr in gv.Rows)
{
CheckBox cb = (CheckBox)gr.Cells[0].FindControl("cbCheckRow");
if (cb.Checked)
{
string prodID = gv.DataKeys[gr.RowIndex].Value.ToString();
tempList.Add(prodID);
for (int count = 0; count < tempList.Count; count++)
{
lblTest.Text = tempList[count] + ",";
}
}
}
}
}
}
Your approach is right, however you need to consider few more things:
You have to loop through the Repeater's items and find the Panel in
each item.
You have to find the GridView inside the Panel, not in the Repeater.
You have to find the DataKey Value by RowIndex, not by row.
EDIT : To test, add a Label outside the repeater:
<asp:Label ID="lblTest" runat="server" Text=""></asp:Label>
Also change the code to display Id in the label.
After rewriting lbnConfirm_Click() method, it should look like below:
protected void lbnConfirm_Click(object sender, EventArgs e)
{
List<string> tempList = new List<string>();
foreach (RepeaterItem item in Repeater1.Items)
{
if (item.ItemType == ListItemType.Item || item.ItemType == ListItemType.AlternatingItem)
{
Panel pnl = item.FindControl("pBody1") as Panel;
GridView gv = pnl.FindControl("gvProduct") as GridView;
foreach (GridViewRow gr in gv.Rows)
{
CheckBox cb = (CheckBox)gr.Cells[0].FindControl("cbCheckRow");
if (cb.Checked)
{
//GridViewRow row = gv.SelectedRow;
string prodID = gv.DataKeys[gr.RowIndex].Value.ToString();
List<DistributionStandardPackingUnitItems> distSPUList = new List<DistributionStandardPackingUnitItems>();
//Store the prodIDs into list
tempList.Add(prodID);
}
}
}
}
lblTest.Text = string.Join(",", tempList);
}
The code above worked fine in my test! Only you have to be careful not to rebind the repeater at postback in Page_Load().
Hope it helps!
get the row index in the RowDataBound event :
protected void gvProduct_RowDataBound(Object sender, GridViewRowEventArgs e)
{
if(e.commandName=="select")
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
int index = e.Row.RowIndex;
CheckBox chk = (CheckBox)e.Row.FindControl("cbCheckRow");
int code = Convert.ToInt32(this.gvProduct.DataKeys[e.Row.RowIndex].Value);
}
}
}

Bind ddl in gridview that is already bound

I am trying to have the ddl bound when the search box returns a result. The DDL is bound as follows:
<asp:TemplateField HeaderText="Service Area" SortExpression="ServiceArea">
<EditItemTemplate>
<asp:DropDownList ID="drp_Val_ServiceArea" runat="server" DataTextField="ServiceArea"
DataValueField='<%# Eval("ServiceAreaId") %>'>
</asp:DropDownList>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="lbl_Bind_ServiceArea" runat="server" Text='<%# Bind("ServiceArea") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
The page loads fine when I use the search and the grid loads.
When I press the edit button the exception is Object not set to an instance.
And errors on ddl.DataTextField = "ServiceArea".
protected void grd_User_RowEditing(object sender, GridViewEditEventArgs e)
{
grd_User.EditIndex = e.NewEditIndex;
using (var _db = new dbDataContext())
{
var result = from s in _db.tbl_ServiceAreas
where s.Deleted == false
select new
{
s.ServiceAreaId,
s.ServiceArea
};
if ((DataControlRowState.Edit) > 0)
{
DropDownList ddl = (DropDownList)grd_User.Rows[e.NewEditIndex].Cells[0].FindControl("drp_Val_ServiceArea");
ddl.DataTextField = "ServiceArea";
ddl.DataValueField = "ServiceAreaId";
ddl.DataSource = result;
ddl.DataBind();
}
}
LoadGrid();
}
Is this because the grid is already bound to the ServiceArea?
Below is the Answer I have been looking for.
protected void grd_User_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowState == DataControlRowState.Edit)
{
DropDownList ddl = (DropDownList)e.Row.FindControl("drp_Val_ServiceArea");
using (var _db = new dbDataContext())
{
var result = from s in _db.tbl_Users
where s.Deleted == false
select new
{
s.ServiceAreaId,
s.tbl_ServiceArea.ServiceArea
};
foreach (var item in result)
{
ddl.DataTextField = item.ServiceArea;
ddl.DataValueField = item.ServiceAreaId.ToString();
ddl.DataSource = result;
ddl.DataBind();
}
}
}
}

Categories

Resources