asp.net create uzer wizard getting a handle on controls in custom steps - asp.net

I have added an extra step to my uzerwizard
<asp:TemplatedWizardStep id="stpPayment" runat="server" Title="Payment">
<ContentTemplate>
<asp:DropDownList ID="cmbSubs" runat="server" ClientIDMode="Static"
Width="200px">
<asp:ListItem Value="month">Monthly Subscription</asp:ListItem>
<asp:ListItem Value="year">Annual Subscription</asp:ListItem>
</asp:DropDownList>
i am successfully navigating to the new step
protected void NewUserprofileWizard_NextButtonClick(object sender, WizardNavigationEventArgs e)
{
if (NewUserprofileWizard.ActiveStepIndex == 0)
{
NewUserprofileWizard.ActiveStepIndex = 1;
}
}
but I cant get access to the dropdownlist from my codebehind
note: i can get a handle onto the controls in the 1st (createuser) step.
but any controls in the next step always return a null.
this is the code i am using
DropDownList cmb = (DropDownList)NewUserprofileWizard.WizardSteps[1].FindControl("cmbSubs");
i always return a null.
note that this works just fine
TextBox tmp = (TextBox)NewUserprofileWizard.CreateUserStep.ContentTemplateContainer.FindControl("Email");
userProfile.AccountEmail = tmp.Text;
problem seems unique to custom steps
Thanks for the help
Tried Gregors suggestion. no luck. mine always comes up as null.
if thsi helps any:
my wizard is inside a user control..
the page that uses the user control is inside a master page.....

Here is little sample I have created for you, first aspx code:
<asp:CreateUserWizard ID="CreateUserWizard1" runat="server" OnNextButtonClick="CreateUserWizard1_NextButtonClick">
<WizardSteps>
<asp:WizardStep runat="server" Title="My Custom Step">
<asp:DropDownList ID="cmbSubs" runat="server" ClientIDMode="Static"
Width="200px">
<asp:ListItem Value="month">Monthly Subscription</asp:ListItem>
<asp:ListItem Value="year">Annual Subscription</asp:ListItem>
</asp:DropDownList>
</asp:WizardStep>
<asp:CreateUserWizardStep runat="server" />
<asp:CompleteWizardStep runat="server" />
</WizardSteps>
</asp:CreateUserWizard>
And now the code to find first dropdown:
protected void CreateUserWizard1_NextButtonClick(object sender, WizardNavigationEventArgs e)
{
if (e.CurrentStepIndex == 0)
{
//get instance to dropdown...
string selectedValue = null;
string controlId = null;
foreach (var item in CreateUserWizard1.WizardSteps[0].Controls)
{
DropDownList ddl = item as DropDownList;
if (ddl != null)
{
selectedValue = ddl.SelectedValue;
controlId = ddl.ClientID;
break;
}
}
}
}
Of course you can also find your dropdown like this:
DropDownList cmbSubs = CreateUserWizard1.WizardSteps[0].FindControl("cmbSubs") as DropDownList;
Happy coding!

it appears that today my google foo was doing much better
because i am in a templateswizardstep, i have to cast the wizardstep into the templatedwizardstep.
from here i can now find the control. whooohoo!
TemplatedWizardStep step = (TemplatedWizardStep)NewUserprofileWizard.WizardSteps[1];
cmb = (DropDownList)step.ContentTemplateContainer.FindControl("cmbSubs");
Thanks all for the help

Related

Asp.net C# - checkbox control won't stay true after code-behind runs

Front HTML
<asp:CheckBox ID="chkSend" runat="server" Text="Send?" />
The code that triggers the code behind
<asp:DropDownList ID="ddlStatus" OnSelectedIndexChanged="ddlStatus_SelectedIndexChanged" AutoPostBack="true"
runat="server" DataValueField="Id" DataTextField="Status" />
The code that runs in the code behind
protected void ddlStatus_SelectedIndexChanged(object s, EventArgs e)
{
this.chkSend.Checked = True;
}
When get back to the front end , the checkbox isn't checked. Any Ideas?
If it helps, this particular view is using Multi-views to which I'm new to.

Custom validator message not displaying

VS2013, WebForms, .NET 4.51
I have a FormView defined and in my EditTemplate I have as follows:
<div class="form-group">
<asp:Label ID="lblClientClassification" CssClass="col-md-2 control-label" runat="server" for="cblClientClassifications" Text="Kind"></asp:Label>
<div class="col-md-5">
<asp:CheckBoxList ID="cblClientClassifications" runat="server"></asp:CheckBoxList>
<asp:CustomValidator ID="cfvClientKinds" runat="server" Display="Dynamic" CssClass="label label-danger" ErrorMessage="XXXX" ValidationGroup="Default" OnServerValidate="cfvClientClassifications_OnServerValidate"></asp:CustomValidator>
</div>
and then in the code behind:
protected void cfvClientClassifications_OnServerValidate(object aSource, ServerValidateEventArgs aArgs)
{
CustomValidator cvCheckBoxKinds = aSource as CustomValidator;
int checkedCount = 0;
if (cvCheckBoxKinds != null)
{
CheckBoxList cblClientClassifications = GuiClientClassificationsFind();
foreach (ListItem listItem in cblClientClassifications.Items)
{
if (listItem.Selected)
{
checkedCount++;
}
}
if (checkedCount == 0)
{
aArgs.IsValid = false;
cvCheckBoxKinds.ErrorMessage = "Select client kind.";
}
}
}
The OnServerValidate is firing and I am getting to set the validator to invalid as well as setting the error message (Page.IsValid is also false as expected). However, the error text is not displaying. When I view the page source I see:
<span id="ctl00_cphMainContent_fvData_cfvClientKinds" class="label label-danger" style="display:none;">XXXX</span>
instead of the error message I set as well as the fact that it is not visible.
Has anyone got any pointers here on how to track this down? I have looked at similar questions of SO but none of the comments seem to apply. Is this related to FormView perhaps?
Try your control without the CssClass="label label-danger" bootstrap first, and use the code below to check your boxes:
protected void cfvClientKinds_ServerValidate(object aSource, ServerValidateEventArgs aArgs)
{
aArgs.IsValid = cblClientClassifications.SelectedItem != null;
cfvClientKinds.ErrorMessage = "Hey! this is a new message";
}
and I guess you call this line before you fire the above event:
protected void btnValidate_Click(object sender, EventArgs e)
{
Page.Validate();
}
In Short, I think that your problem is either related to your way of finding cblClientClassifications checkBoxList or other code that you haven't stated above.
CheckBoxList cblClientClassifications = GuiClientClassificationsFind();
I decided to try out your case and created a new webform added formview and bind it to northwind categories table then inside edititemtemplate I added a checkboxlist and populated it manually. added CustomValidator double clicked it copied your codebehind and it works for me except for the findcontrol part: GuiClientClassificationsFind();
Here is the formview:
<asp:FormView ID="FormView1" runat="server" DataKeyNames="CategoryID" DataSourceID="SqlDataSource1">
<EditItemTemplate>
...
<asp:CheckBoxList ID="cblClientClassifications" runat="server">
<asp:ListItem>Bir</asp:ListItem>
<asp:ListItem>iki</asp:ListItem>
<asp:ListItem>Üç</asp:ListItem>
<asp:ListItem>Dört</asp:ListItem>
</asp:CheckBoxList>
<asp:CustomValidator ID="cfvClientKinds" runat="server" Display="Dynamic" CssClass="label label-danger" ErrorMessage="CustomValidator" OnServerValidate="cfvClientKinds_ServerValidate"></asp:CustomValidator>
<br />
<asp:LinkButton ID="UpdateButton" runat="server" CausesValidation="True" CommandName="Update" Text="Update" />
<asp:LinkButton ID="UpdateCancelButton" runat="server" CausesValidation="False" CommandName="Cancel" Text="Cancel" />
</EditItemTemplate>
</asp:FormView>
And codebehind with your code:
protected void cfvClientKinds_ServerValidate(object aSource, ServerValidateEventArgs aArgs)
{
CustomValidator cvCheckBoxKinds = aSource as CustomValidator;
CheckBoxList cblClientClassifications = (CheckBoxList)FormView1.FindControl("cblClientClassifications");
int checkedCount = 0;
if (cvCheckBoxKinds != null)
{
foreach (ListItem listItem in cblClientClassifications.Items)
{
if (listItem.Selected)
{
checkedCount++;
}
}
if (checkedCount == 0)
{
aArgs.IsValid = false;
cvCheckBoxKinds.ErrorMessage = "Select client kind.";
}
}
}
I Ali Shahrokhi's method is shorter and works as well as yours..
protected void cfvClientKinds_ServerValidate(object aSource, ServerValidateEventArgs aArgs)
{
CustomValidator cvCheckBoxKinds = aSource as CustomValidator;
CheckBoxList cblClientClassifications = (CheckBoxList)FormView1.FindControl("cblClientClassifications");
aArgs.IsValid = cblClientClassifications.SelectedItem != null;
cvCheckBoxKinds.ErrorMessage = "Select client kind.";
}
if you check as you entered edititemtemplate in formview you'll see before submitting that your customvalidators span will be there just as you mentioned that's because server hasn't sent it to the client yet somehow.

RegisterStartupScript from code behind not working when Update Panel is used

I have created a radiobutton list followed by one button. I can select one of the item from the radiobutton list and then click the button to execute something. And I want the page to pop up a window if the button is clicked without selecting any of the options from the radiobutton list. My codebehide is like this:
protected void ButtonPP_Click(object sender, EventArgs e)
{
if (radioBtnPP.SelectedIndex < 0)
{
String csname1 = "PopupScript";
Type cstype = this.GetType();
// Get a ClientScriptManager reference from the Page class.
ClientScriptManager cs = Page.ClientScript;
// Check to see if the startup script is already registered.
if (!cs.IsStartupScriptRegistered(cstype, csname1))
{
StringBuilder cstext1 = new StringBuilder();
cstext1.Append("<script type=text/javascript> alert('Please Select Criteria!') </");
cstext1.Append("script>");
cs.RegisterStartupScript(cstype, csname1, cstext1.ToString());
}
}
}
and my html part is:
<asp:RadioButtonList class ="radioBtn" ID="radioBtnACO" runat="server">
<asp:ListItem Text="All Dim" />
<asp:ListItem Text="Select Dim" />
</asp:RadioButtonList>
<asp:Button id ="ButtonPP" class ="buttonRight" runat="server" Text="Run PP" OnClick="ButtonPP_Click" />
This works fine. However, now I don't want to refresh the whole page when i click the button, so I use updatepanel. And I changed my html code to the following:
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:UpdatePanel ID="ControlUpdatePanel" runat="server" Visible="True">
<ContentTemplate>
<asp:RadioButtonList class ="radioBtn" ID="radioBtnACO" runat="server">
<asp:ListItem Text="All Dim" />
<asp:ListItem Text="Select Dim" />
</asp:RadioButtonList>
<asp:Button id ="ButtonPP" class ="buttonRight" runat="server" Text="Run PP" OnClick="ButtonPP_Click" />
</ContentTemplate>
</asp:UpdatePanel>
But now my code doesn't work anymore... If I don't select any option from the radiobutton list and just click the button, no window would pop up :( I am sure my codebehind is still executed but seems like it just doesn't passed to my .aspx page...
Anyone please help me out? I don't know what to do now... Millions of thanks!
You need to use ScriptManager.RegisterStartupScript for Ajax.
protected void ButtonPP_Click(object sender, EventArgs e)
{
if (radioBtnACO.SelectedIndex < 0)
{
string csname1 = "PopupScript";
var cstext1 = new StringBuilder();
cstext1.Append("alert('Please Select Criteria!')");
ScriptManager.RegisterStartupScript(this, GetType(), csname1,
cstext1.ToString(), true);
}
}

Ajax autocomplete extender and get ID of selected item?

I am using the autocomplete extender to suggest names when a user types. How to get the select value after the user selects an item? I guess I can use onclientitemselected but I am not familiar on how to write this? I need to populate a textbox based on the selection in the autocompleteextender textbox. Thank you
<asp:TextBox ID="TextBox1" runat="server" Height="27px" Width="570px"></asp:TextBox>
<asp:AutoCompleteExtender ID="AutoCompleteExtender" runat="server"
DelimiterCharacters="" Enabled="True" ServicePath="AutoComplete.asmx"
ServiceMethod="GetCompletionList" TargetControlID="TextBox1"
MinimumPrefixLength="2" UseContextKey="true" ContextKey="StateDropDown"
CompletionListElementID="autocompleteDropDownPanel">
</asp:AutoCompleteExtender>
For this you need to return the list from web service method with ID and Text
Here "lst" is the actual list with data from your data source.
List<string> items = new List<string>(count);
for (int i = 0; i < lst.Count; i++)
{
string str =AjaxControlToolkit.AutoCompleteExtender.CreateAutoCompleteItem(lst[i].Text,Convert.ToString(lst[i].IDValue));
items.Add(str);
}
return items.ToArray();
Then simple javascript
function GetID(source, eventArgs )
{
var HdnKey = eventArgs.get_value();
document.getElementById('<%=hdnID.ClientID %>').value = HdnKey;
}
and dont forget to set the attribute in auto complete extender
OnClientItemSelected="GetID"
The AutoCompleteExtender merely extends the ASP.NET TextBox control, so if you want to know when the text changed, then just raise the TextChanged event on the TextBox control, like this:
Markup:
<asp:TextBox ID="TextBox1" runat="server" Height="27px" Width="570px" OnTextChanged="TextBox1_TextChanged" AutoPostBack="true"></asp:TextBox>
Code-Behind:
protected void TextBox1_TextChanged(object sender, EventArgs e)
{
// Do something here with textbox value
}

How do I maintain user entered text in a TextBox nested in an UpdatePanel between updates?

I have an ASP.Net UpdatePanel that updates on a timer. Within the UpdatePanel and nested in a GridView, I have a TextBox that the user enters a value in with a submit button. Everything works fine, except if the user does not submit the value before the timed interval, the text is removed from the TextBox.
Is there a way to persist the user entry into the TextBox between updates? Is there a better way of doing this?
All suggestions welcome.
Respectfully,
Ray K. Ragan
Code Postscript:
aspx:
<script type="text/javascript">
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_beginRequest(beginRequest);
function beginRequest() {
prm._scrollPosition = null;
}
</script>
<asp:Timer ID="Timer1" runat="server" Interval="900" OnTick="Timer1_Tick"></asp:Timer>
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="Timer1" EventName="Tick" />
</Triggers>
<ContentTemplate>
<asp:DataList RepeatColumns="5" RepeatDirection="Horizontal" ID="dlMine" runat="server" OnItemCommand="Item_Command">
<ItemTemplate>
<div style="border:1px solid black;margin:3px;height:300px;text-align:center;padding:5px;">
<div style="width:150px;">
<asp:Label ID="lblTitle" runat="server" Text='<%# left(DataBinder.Eval(Container.DataItem,"title").ToString(), 75) %>'></asp:Label>
</div>
<asp:Label ID="Label1" runat="server" Text='<%# (DateTime)DataBinder.Eval(Container.DataItem,"end_date") %>'></asp:Label>
<br />
<asp:Label ID="Label2" runat="server" Text='<%# String.Format("{0:C}",DataBinder.Eval(Container.DataItem,"current_value")) %>'></asp:Label>
<br />
<asp:TextBox ID="txtNewValue" runat="server"></asp:TextBox>
<asp:Button Visible='<%# (isInThePast((DateTime)DataBinder.Eval(Container.DataItem,"end_date"))) ? false : true %>' CssClass="bid_button" runat="server" CommandArgument='<%# Eval("ID") %>' CommandName="Revalue" ID="btnBid" Text="Submit New Valuation" />
</div>
</ItemTemplate>
</asp:DataList>
</ContentTemplate>
</asp:UpdatePanel>
Codebehind:
protected void Page_Load(object sender, EventArgs e)
{
Timer1.Tick += new EventHandler<EventArgs>(Timer1_Tick);
if (!IsPostBack)
{
dataBindList();
}
}
protected void dataBindList()
{
if (Request.QueryString["GroupID"] != null)//Are they coming here with a URL var? If so, build content object
{
List<Item> itemList = ItemManager.getItemsByGroupID(Request.QueryString["GroupID"].ToString());
dlMine.DataSource = itemList.Take(15);
dlMine.DataBind();
}
}
protected void Timer1_Tick(object sender, EventArgs e)
{
dataBindList();
UpdatePanel1.Update();
}
protected void Item_Command(Object sender, DataListCommandEventArgs e)
{
if (e.CommandName == "Revalue")
{
Person p = (Person)Session["Person"];
foreach (DataListItem item in dlMine.Items)
{
string textBoxText = ((TextBox)item.FindControl("txtNewValue")).Text;
Utilities.writeLog("txtNewValue: " + textBoxText, 1);
}
dataBindList();
UpdatePanel1.Update();
}
}
You're rebinding the DataList every time the Timer ticks. All changes in the ItemTemplates of the DataList will be lost on postback.
Why not use Javascript to "pause" the timer whenver one of the textboxes gains focus. This will prevent the Timer from firing and let users finish entering text. Once they leave the textbox of "onblur" then you can restart the timer.
Update
The following will take a bit of effort to make it happen but you can do something like:
When the Timer posts back, before rebinding, iterate over the DataList while searching for textboxes with text in them. Something like:
foreach (DataListItem item in dlMine.Items)
{
//find the textbox control and check for text
}
At this point, you'll know which rows need there textboxes repopulated. Store this information in a hashtable.
In the DataList ItemDataBound event, check each rowID against the hashtable to see if its corresponding textbox exists. If so, repopulate the textbox in the DataList row.
Are you initializing the TextBbox value in your code-behind, perhaps in Page_Load or another page method?
TextBox1.Text = "";
If so, that code is executing on every timer event. You can prevent that like this:
if (! IsPostback) {
TextBox1.Text = "";
}
The first request that hits an ASP.NET page is usually an HTTP GET request, while ASP.NET buttons and update panel events issue HTTP POST requests. So the code above will clear TextBox1 the first time you access the page, but leave the value alone when receiving requests from itself. (If you really are setting the text box's value to its default - empty - you could just remove the initialization code.)

Resources