Event not firing as expected for control in formview asp.net - asp.net

I have a LinkButton in an InsertItemTemplate which when clicked, should display a hidden DropDownList in the InsertItemTemplate. However, it doesn't seem to be working, but it will say, change the text of a label outside the Formview when the LinkButton is clicked. The event is firing, but the part to make the DropDownList visible in the InsertItemTemplate is not doing anything. Code is below:
.aspx:
<asp:FormView ID="formViewNewRecord" runat="server">
<InsertItemTemplate>
<asp:DropDownList ID="ddlAddSelection2" runat="server" DataSourceID="dSource1" DataTextField="Users" DataValueField="Users" AppendDataBoundItems="true" Visible="false">
<asp:ListItem></asp:ListItem>
</asp:DropDownList>
<asp:LinkButton runat="server" ID="lbAddAnother" OnClick="lbAddAnother_Click">+Add Another</asp:LinkButton>
</InsertItemTemplate>
</asp:FormView>
<asp:Label ID="Label2" runat="server" Text="Label"></asp:Label>
C#:
protected void lbAddAnother_Click(object sender, EventArgs e)
{
DropDownList addSelection2 = (DropDownList)formViewNewItem.Row.Cells[0].FindControl("ddlAddSelection2");
addSelection2.Visible = true;
Label2.Text = addSelection2.ID;
}

Your dropdown control is not an immediate child of your formview. So since the FindControl call is not recursive, you have to search for the control in the right location of your form view's child controls. See this for the details but at a high level, you need something along the lines of:
DropDownList ctrl = (DropDownList)FormView1.Row.Cells[0].FindControl("ddlAddSelection2");
After that, you should check it for null for safe measure.

Related

asp:DropDownList datasource is null after submit when declared inside an asp:UpdatePanel

I am using a DropDownList in an UpdatePanel. It fills when the user writes some text in the TextBox and click the "Go" Button.
xaml is as follow :
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:TextBox ID="ODSearchTB" runat="server" ClientIDMode="Static"></asp:TextBox>
<asp:Button ID="ODFindButton"
class="btn btn-default goButton"
runat="server" Text="Go"
ClientIDMode="Static"
UseSubmitBehavior="False"
CausesValidation="False"
OnClick="ODFindButton_Click" /><br/>
<asp:DropDownList ID="ODSearchDDL" runat="server" Visible="False" AutoPostBack="True"></asp:DropDownList>
</ContentTemplate>
</asp:UpdatePanel>
and the code behind that fills the DropDownList on click :
protected void ODFindButton_Click(object sender, EventArgs e)
{
var res = ServiceUnitOfWork.MedicalOffices.FindMedicalOfficesByName(
ODSearchTB.Text,
doctor: false,
hospital: true,
service: false,
establishment: true);
List<LightMedicalOffice> source = getLightMedicalOffices(res.ToList());
ODSearchDDL.DataSource = source;
ODSearchDDL.DataTextField = "Name";
ODSearchDDL.DataValueField = "IdAddress";
ODSearchDDL.DataBind();
ODSearchDDL.Visible = true;
}
This works fine, the datasource will update properly and the DropDownList will be filled and updated (in the UpdatePanel) without the page reloading. The problem occurs when the form is submitted : the DropDownList is empty (datasource null) in the Page_Load event so when I reach the Submit_Click and the CustomValidator_ServerValidate events, I can't know what was the selected value of the list.
The ViewState seems to be enabled on both the page and the control. I have no clue to what could cause such a behavior.
Do you reset the DropDown in the Page_Load event? I implemented your code above, and added a submit button outside of the update panel. I was able to capture the value of the DropDown control within my OnClick event of the submit button.

How to assign UpdatePanel Trigger's control ID with button's from gridview

currently I have a UpdatePanel for jQuery Dialog use, which contains a GridView.
And that GridView contains a FileUpload control in footer and EmptyDataTemplate
In order to get FileUpload control work in javascript, I know that we need trigger.
However, the button that I wanna assign as trigger is inside GridView's template...
when the button btnAdd clicked, file in FileUpload control will be saved.
Here is the code:
<asp:UpdatePanel ID="upnlEditExpense" runat="server">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="btnAdd"/>
</Triggers>
......................
........................
.........................
<asp:GridView runat="server" ID="grdExpense" ShowHeader="True" ShowFooter="True"
AutoGenerateColumns="False">
<Columns>
...................
<asp:TemplateField>
<FooterTemplate>
<asp:LinkButton runat="server" ID="btnAdd" Text="Add" OnClick="btnAdd_Click"></asp:LinkButton>
</FooterTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</asp:UpdatePanel>
If I put the button id directly in trigger's control ID like this, error come up saying btnAdd could not be found...
what should I do to get FileUpload control work?
This works
protected void grdExpense_RowCreated(object sender, GridViewRowEventArgs e)
{
LinkButton btnAdd = (LinkButton)e.Row.Cells[0].FindControl("btnAdd");
if (btnAdd != null)
{
ScriptManager.GetCurrent(this).RegisterPostBackControl(btnAdd);
}
}
Try registering the post back control from code behind like this:
protected void grdExpense_RowCreated(object sender, GridViewRowEventArgs e)
{
LinkButton btnAdd = (LinkButton)e.Row.Cells[0].FindControl("btnAdd");
if (btnAdd != null)
{
ScriptManager1.RegisterAsyncPostBackControl(btnAdd);
}
}
Instead of adding a trigger to upnlEditExpense maybe you can try to add an update panel around the link button inside the template with no triggers...
<asp:TemplateField>
<FooterTemplate>
<asp:UpdatePanel ID="upnlBtnAdd" runat="server">
<ContentTemplate>
<asp:LinkButton runat="server" ID="btnAdd" Text="Add" OnClick="btnAdd_Click"></asp:LinkButton>
</ContentTemplate>
</asp:UpdatePanel>
</FooterTemplate>
</asp:TemplateField>
I had a similar problem and this post helped me, but I found that registering the control in the scriptmanager works only if the updatepanels UpdateMode is set to "Always". If its set to "Conditional" this approach does not work.
I found another approach that always works which is to add triggers to the updatepanel in the DataBound() event of the gridview:
Dim CheckBoxTrigger As UpdatePanelControlTrigger = New AsyncPostBackTrigger()
Dim SelectCheckBox As CheckBox
For i = 0 To GridViewEquipment.Rows.Count - 1 Step 1
SelectCheckBox = GridViewEquipment.Rows(i).Cells(12).FindControl("CheckBoxSign")
CheckBoxTrigger.ControlID = SelectCheckBox.UniqueID
UpdatePanelEquipment.Triggers.Add(CheckBoxTrigger)
Next

Lost Focus Events for a Control Within GridView

I have multiple textboxes and dropdown lists within my GridView. For one particular textbox I need trigger a server event which gets data from the database and fills it in other columns of the Grid. Is there a simple way to do it or a slightly complicated way as detailed here
I have no problems implementing the above method or thinking of a work around but then thought that there is Cell Lost Focus in a grid control surprises me a little. Am I missing something ? Any help on this would appreciated.
You can set AutoPostBack to true and handle it's TextChanged event.
<asp:GridView ID="GridView1" runat="server" EmptyDataText="It's Empty.">
<Columns>
<asp:TemplateField HeaderText="Name">
<ItemTemplate>
<asp:TextBox ID="txtName"
runat="server"
Text='<%#Eval("Name") %>'
AutoPostBack="true"
OnTextChanged="NameChanged" >
</asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</GridView>
in codebehind:
protected void NameChanged(Object sender, EventArgs e)
{
var txtName = (TextBox) sender;
var row = (GridViewRow) txtName.NamingContainer;
// you could find other controls in this GridViewRow via
// row.FindControl("ControlID") in case of a TemplateField or
// row.Cells[0].Text (0 = index of column) in case of a BoundField
}

RadioButtonList inside UpdatePanel inside Repeater, Can I?

I have a repeater with a RadioButtonList inside the ItemTemplate, but when the RadioButtonList.OnSelectedIndexChanged event fires it generates a full postback. What have I done wrong in my code below? How can I get the OnSelectedIndexChanged to generate an Async Postback?
<asp:UpdatePanel runat="server" ID="UpdatePanel2">
<ContentTemplate>
<asp:Repeater ID="Repeater1" runat="server" DataSourceID="sqlOptions">
<ItemTemplate>
<asp:UpdatePanel runat="server" ID="pnlA">
<ContentTemplate>
<strong>
<%# Eval("Name") %></strong><br />
<asp:RadioButtonList ID="RadioButtonList1"
DataSourceID="sqlOptionValues" runat="server"
DataTextField="id" DataValueField="Id" AutoPostBack="true"
OnSelectedIndexChanged="LoadPrice"
ValidationGroup="options" />
<asp:RequiredFieldValidator ID="RequiredFieldValidator1"
ForeColor="Red" runat="server"
ControlToValidate="RadioButtonList1"
ErrorMessage="Required Field"
ValidationGroup="options" />
<asp:SqlDataSource ID="sqlOptionValues" runat="server"
ConnectionString="<%$ ConnectionStrings:
ConnectionString6 %>"
SelectCommand='<%# "SELECT DISTINCT OptionValue.Name,
OptionValue.Id FROM CombinationDetail
INNER JOIN OptionValue
ON CombinationDetail.OptionValueId = OptionValue.Id
WHERE (OptionValue.OptionId =" +
Eval("Id") + ")" %>'>
</asp:SqlDataSource>
<br />
</ContentTemplate>
</asp:UpdatePanel>
</ItemTemplate>
</asp:Repeater>
</ContentTemplate>
</asp:UpdatePanel>
Many thanks for any help :)
This is a real-world use case. I have a page with Repeaters, Ajax Accordions inside of other Accordions, Update Panels inside other Update panels, you name it. The page works great, except when I want to update one of the Accordion panels with my RadioButtonList (RBL). Even with the RBL inside an update panel, it causes a postback of the entire page. I tried everything. I finally realized it wasn't me when I noticed my buttons would work just fine. I figure it must be a bug in either the framework or the Ajax Control Toolkit. I did find people reference this link all over the web (http://blog.smarx.com/posts/the-case-of-the-radiobuttonlist-half-trigger.aspx), but this link from 2007 is dead now and probably no longer applicable, so that's no help.
What I ended up doing was going with what works - that submit button. All I did was add an onclick attribute to the RBL to call a hidden button. Now you don't want to set the button to Visible=false because then the button won't appear in the generated markup. Instead, set the button's style to display:none; so that no one will see this hack, because yes, that's what this workaround is - it's a hack, but simple and just as effective as what you'd expect. Don't forget to remove the Autopostback="True" from your RBL.
CAVEAT: Because I'm using a hacked button for the onclick event, it's possible for the user to click in the area of the RBL, but not actually select an item. When this happens, our onclick triggers an AsyncPostBack and the codebehind logic will be processed, so please keep that in mind. To give you an idea of what I mean: all the Page_Load() events will be called, but rbl_Questions_SelectedIndexChanged() won't be if they happen to click in the area of the RBL without actually selecting an item. For my purposes this causes no issues in my logic and has no effect on the user.
Here's the Code:
Somewhere In the .Aspx Page:
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:RadioButtonList ID="rbl_Questions" runat="server"
OnSelectedIndexChanged="rbl_Questions_SelectedIndexChanged">
</asp:RadioButtonList>
<asp:Button ID="btn_rbl_Questions" runat="server" style="display:none;"/>
<asp:Label ID="lbl_Result" runat="server" Text="" Visible="false">
</asp:Label>
</ContentTemplate>
</asp:UpdatePanel>
In the Page_Load() event:
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack == false)
{
//Instead of using the AutoPostback of the RBL, use this instead.
rbl_Questions.Attributes.Add("onclick",
"document.getElementById('"
+ btn_rbl_Questions.ClientID
+ "').click();");
//Bind your RBL to a DataSource, add items programmatically,
// or add them in the aspx markup.
}
}
In the rbl_Questions_SelectedIndexChanged() event:
protected void rbl_Questions_SelectedIndexChanged(object sender, EventArgs e)
{
//Your code here.
//My code unhid the lbl_Result control and set its text value.
}
Update 05/24/2011
The above "hack" is no longer necessary (I am leaving it above since this was marked as the answer by the author). I have found the best way to do this, thanks to this SO Answer:
Updatepanel gives full postback instead of asyncpostback
The code is much simpler now, just remove what I put in the Page_Load() method and remove the Button I used in the Aspx page and add ClientIDMode="AutoID" and AutoPostBack="True" to the control you want the UpdatePanel to capture.
Somewhere In the .Aspx Page:
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:RadioButtonList ID="rbl_Questions" runat="server"
ClientIDMode="AutoID" AutoPostBack="true"
OnSelectedIndexChanged="rbl_Questions_SelectedIndexChanged">
</asp:RadioButtonList>
<asp:Label ID="lbl_Result" runat="server" Text="" Visible="false">
</asp:Label>
</ContentTemplate>
</asp:UpdatePanel>
MS changed how ClientID's are generated in .net 4.0 from "AutoID" to "Predictable" and I guess the ScriptManager or UpdatePanel's weren't updated correctly to use it. I can't find documentation on why that is anywhere or if it was left that way by design.
I seriously don't miss winforms.
Try this:
<asp:UpdatePanel runat="server" UpdateMode="Conditional" ID="pnlA">
You'll also need to setup
<Triggers>
//radio buttons
</Triggers>
Not sure how you'll do that since it's a dynamically built list.

give the ID as a custom attribute to checkbox in a grid for manual update

I like to update just the value of my checkbox in a asp grid.
so i thought i bind the id to the checkbox ( but how?) and fire an update in code behind by clicking the checkbox.
but how can I get the ID, and where I have to bind this id to get it in code behind in the event?
Thanks
Here is what I've managed to do. (Be aware there should be an easier way to do this. I'm very new to ASP.NET)
Here you have a TemplateField in a GridView. Inside it there is an UpdatePanel and the CheckBox is inside it. This is done to make the checking of the TextBox do post in the backgroung (ajax). You might not need it (UpdatePanel) at all.
<asp:TemplateField HeaderText="Private" SortExpression="IsPrivate">
<ItemTemplate>
<asp:UpdatePanel ID="upIsPrivate" runat="server" UpdateMode="Always" ChildrenAsTriggers="true">
<ContentTemplate>
<asp:CheckBox ID="chkIsPrivate" runat="server" OnCheckedChanged="chkIsPrivate_CheckedChanged" AutoPostBack="true" />
</ContentTemplate>
</asp:UpdatePanel>
</ItemTemplate>
</asp:TemplateField>
And this is the method that handles this. Notice that I get the Id from the GridViewRow that contains the CheckBox:
GridViewRow row = (GridViewRow)((CheckBox)sender).Parent.Parent.Parent.Parent;
protected void chkIsPrivate_CheckedChanged(object sender, EventArgs e)
{
if (editMode)
{
GridViewRow row = (GridViewRow)((CheckBox)sender).Parent.Parent.Parent.Parent;
Int32 id = (Int32)uxPhoneCallList.DataKeys[row.RowIndex]["Id"];
CheckBox isPrivate = (CheckBox)row.FindControl("chkIsPrivate");
PhoneCall phoneCall = PhoneCallManager.GetById(id);
...
}
}

Resources