ASP.NET unable to search without using invisible button - c#

I'm trying to make my first ASP.NET web site and am unable to get searching and paging to work in ASP.NET Web Forms without using an invisible button. I can't use my search button's click event because it needs to reset my page to 0 when clicked, so it only has a client-click event. I have to make it call a JavaScript function, which calls the invisible button's click event handler after doing so. The only way I can figure out around it is to make the page post back to itself and pass the index in from the bottom paging table. Hopefully, someone here might have some suggestions for an easier way to do it. Thanks in advance for any suggestions. If it wasn't for paging, it would be one line of code inside my button click event handler.
Here is the relevant markup for my page.
<script language="javascript">
function page(index)
{
document.getElementById('PageIndex').value = index;
document.getElementById('btnInvisible').click();
}
</script>
<uc1:ucWidgetSearch runat="server" id="ctl" />
<p id="pHTML" runat="server"/>
<asp:Button ID="btnInvisible" runat="server" BackColor="White"
BorderStyle="None" BorderWidth="0px" OnClick="btnInvisible_Click" />
<asp:HiddenField ID="PageIndex" runat="server" /
Here is the markup for the UserControl on the page.
<label>Last Name:</label>
<asp:TextBox ID="txtLastName" runat="server" MaxLength="50" Enabled="false"></asp:TextBox>
<asp:Button ID="btnSearch" runat="server" Text="Search" OnClientClick="page('0')" />
Here is the C# code behind for the .aspx page. The .aspx page uses no using statements.
namespace Widgets.WebUI
{ public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, System.EventArgs e)
{ ScreenHelper.LoadScreen(ctl.Search(), pHTML, PageIndex);}
protected void btnInvisible_Click(object sender, System.EventArgs e)
{ }
}
}
Here is the code behind for the UserControl. It also uses no using statements.
public partial class ucWidgetSearch : System.Web.UI.UserControl
{
internal Widgets.BLL.WidgetSearch Search()
{
if (!txtLastName.Enabled)
{
txtLastName.Enabled = true;
txtLastName.Focus();
return null;
}
return new Widgets.BLL.WidgetSearch(txtLastName.Text);
}
}
Finally, there is a ScreenHelper class that calls into the BLL layer, which calls into the DAL layer and constructs an HTML document and passes it into the p element on the main page.
internal class ScreenHelper
{
internal static void LoadScreen(WidgetSearch search,
System.Web.UI.HtmlControls.HtmlGenericControl p, HiddenField page)
{
if (search != null)
{
try
{
p.InnerHtml = WidgetsLogic.GetHTMLTable(search.LastName, int.Parse(page.Value), 20);
}
catch (System.Exception ex)
{
p.InnerHtml = "<label style=\"color: #FF0000\">Error loading screen: " + ex.Message + "</label>";
}
}
}
}
namespace Widgets.BLL
{
public class WidgetsLogic
{
public static string GetHTMLTable(string name, int pageIndex, int? pageSize)
{
StringBuilder strBuilder = new StringBuilder("<table border=\"1\">");
List<Widget> list = WidgetsDataAccess.GetByName(name);
int minDex = 0, maxDex = list.Count;
if (pageSize == null)
{
pageIndex = 0;
}
else
{
pageIndex = HTMLHelper.GetPageIndex(pageIndex, pageSize.Value, list.Count);
minDex = pageIndex * pageSize.Value;
maxDex = minDex + pageSize.Value;
if (maxDex > list.Count)
maxDex = list.Count;
}
for (int i = minDex; i < maxDex; i++)
{
strBuilder.Append("<tr");
// Set Light Gray Color for alterating rows in table
if (i%2 != 0)
strBuilder.Append(" style=\"background-color: #EBEBEB\"");
strBuilder.Append("><td>" + list[i].ID.ToString() + "</td>");
strBuilder.Append("<td>" + list[i].Name + "</td></tr>");
}
strBuilder.Append("</table>");
// Add Paging if appropriate
if (pageSize != null && pageSize.Value < list.Count)
{
strBuilder.Append(HTMLHelper.GetPagingFooter(pageIndex, pageSize.Value,
list.Count, "javascript:page('#pageIndex')"));
}
string str = strBuilder.ToString();
return str;
}
}

you should never try to do paging manually. Rather use GridView and an ObjectDataSource
to bind data to your page. This way ASP.NET handles the pageIndex exc via viewstate and the ObjectDatasource handles paging for you.Check this link for a good example of how to do just that.

Use ClientID to refer to the actual ID of an HTML control
document.getElementById('<%= PageIndex.ClientID %>').value = index;

Related

add dynamic button click event c#

with json data, created a table with for loop and added dynamic buttons in different conditions, am looking how to add one onclick event for all buttons and get the value of clicked button value or id.
Thank you for your help
dynamic jsondata = JsonConvert.DeserializeObject(responseData);
for (int i = 0; i < jsondata.val.Count; i++)
{
htmlTable.AppendLine("<tr>");
htmlTable.AppendLine("<td>"+jsondata.val[i].id+"</td>");
htmlTable.AppendLine("<td>"+jsondata.val[i].Name+"</td>");
htmlTable.AppendLine("<td>"+jsondata.val[i].desc+"</td>");
string getStatus = GetStatus(url);
if(getStatus=="0")
htmlTable.AppendLine("<td>" + "<input id='ctb"+i+ "' type='button' value='START'></td>");
else if(getStatus=="1")
htmlTable.AppendLine("<td>" +"<input id='ctb"+i+ "' type='button' value='STOP'></td>");
else
htmlTable.AppendLine("<td>" + "<label> Error Occured </label></td>");
htmlTable.AppendLine("</tr>");
}
htmlTable.AppendLine("</table>");
litTable.Text = htmlTable.ToString();
This is a simple demo, But you can do the same in your scenario as well. I just implemented this sample in WebForm. If I am mistaken do comment please.
public partial class Sample : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
divContainer.InnerHtml = "<div id='mysamplecontrol' onclick='thisismyclick(this);'>Start</div>";
}
}
<form id="form1" runat="server">
<div runat="server" id="divContainer"></div>
<script>
function thisismyclick(control) {
alert(control.id);
}
</script>
</form>

javascript open modal window return values,, i dont get it?

I am not getting this Modal window / javascript stuff , I’m a bit of a noob I ve found tons of stuff about this trawling around
But its hard to find the answer when you lack the experience to ask the correct question.
and are not up to speed with all the jargon either
System.windows.froms.messagebox doesn’t work in a web situation.. I’ve discovered that much,,, This is an intranet application
How do I evaluate the result of the javascript function OpenDialogue() in a similar way to declaring DialogResult myVar =
I have a button event handler like this
protected void but_Comds(object sender, EventArgs e)
{
GridViewRow row = results.SelectedRow;
string crn = Convert.ToString(row.Cells[13].Text);
if (sender == but_crn)
{
checkData(row, crn);
}
}
Then some methods
private void checkData(GridViewRow row, string crn)
{
if (stuff)
{
DialogResult checkCrn = System.Windows.Forms.MessageBox.Show("a mesage",
"Data Check",
MessageBoxButtons.YesNoCancel);
if (checkCrn == DialogResult.No)
{
Do stuff;
}
if (checkCrn == DialogResult.Cancel)
{
Do other stuff;
}
}
else
{
Do stuff instead
}
}
I can get the dialogue to run easy enough as a child page but I can’t work out capture the return value from the child page.
I have been trying to wrap it into a method amongst other things
And I can see this doesn’t work because ClientScript.RegisterStartupScript Is void.
protected string MsgDialogue()
{
Return ClientScript.RegisterStartupScript(this.GetType(),
"newWindow", String.Format("<script>OpenDialog();</script>"));
}
I have also tried okClicked(object sender, eventargs e) methods in the childs code behind
And tried to write a variable into the MySession class and then get that variable in the checkData (row, crn) method
There must be some simple more elegant way of doing this without having to trawl thousands of pages
Hoping to stumble on it..
Here is my javascript on the mainpage
<script type="text/javascript">
function OpenDialog() {
// get the control values
var str1 = 'test';
// create an array with the values
var winArgs = new Array(str1);
var winSettings = 'center:yes;resizable:no;help:no;status:no;dialogWidth:250px;dialogHeight:200px';
// return the dialog control values after passing them as a parameter
winArgs = window.showModalDialog('child.aspx', winArgs, winSettings);
// see if the array is null
if (winArgs == null) {
window.alert('no data returned!');
}
return winArgs;
}
</script>
Here is child.aspx
<head runat="server">
<title></title>
<base target="_self"/>
<script type="text/javascript">
function GetData() {
// intialize variables and array to empty
var str1 = '';
var winArgs = new Array(str1);
// get the values as arguments and set the controls
winArgs = window.dialogArguments;
document.getElementById('TextBox1').value = winArgs[0];
}
function but_ok() {
window.returnValue = "ok";
window.close();
}
function but_cancel() {
window.returnValue = "cancel";
window.close();
}
function but_yes() {
window.returnValue = "yes";
window.close();
}
function but_no() {
window.returnValue = "no";
window.close();
}
</script>
</head>
<body onload="GetData()">
<form id="form1" runat="server">
<div>
<asp:TextBox ID="TextBox1" runat="server" ReadOnly ="true"></asp:TextBox>
<asp:Button ID="dlg_ok" runat="server" Text=" OK " />
<asp:Button ID="dlg_cancel" runat="server" Text=" Cancel " />
<asp:Button ID="dlg_yes" runat="server" Text=" Yes " />
<asp:Button ID="dlg_no" runat="server" Text=" No " />
</div>
</form>
</body>
</html>
And child.aspx. cs
public class child : System.Web.UI.Page
{
protected global::System.Web.UI.HtmlControls.HtmlForm form1;
protected global::System.Web.UI.WebControls.TextBox TextBox1;
protected global::System.Web.UI.WebControls.Button dlg_ok;
protected global::System.Web.UI.WebControls.Button dlg_cancel;
protected global::System.Web.UI.WebControls.Button dlg_yes;
protected global::System.Web.UI.WebControls.Button dlg_no;
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
dlg_ok.Attributes["onclick"] = "javascript:but_ok()";
dlg_cancel.Attributes["onclick"] = "javascript:but_cancel()";
dlg_yes.Attributes["onclick"] = "javascript:but_yes()";
dlg_no.Attributes["onclick"] = "javascript:but_no()";
}
}
}
Sorry ive posted quite a bit of code but hopefully if you can see what I’m trying to do
Then you might be able to better explain what I’m not getting.

Register which anchor tag made a postback?

There a two different navigation menues on a page in their own seperate usercontrols. The menu items in the two menus can navigate to the same pages.
The topmenu has some jQuery animation and the leftmenu has not.
The question is how can I get which anchor tag in a navigation menu made a postback when the anchor tag is in a repeater and the repeater is in a usercontrol(The anchor tags are dynamically created). The problem is that the topmenu usercontrol codebehind runs and sets some values for hiddenfields so the jQuery animation will run properly for the topmenu, but when the leftmenu is clicked it should not run and set the hiddenfields in the topmenu codebehind. So I need to figure out how to differentiate between the two menus.
Here is the repeater markup:
<asp:Repeater runat="server" ID="RightSide">
<HeaderTemplate><ul></HeaderTemplate>
<ItemTemplate>
<li data-type="<%# ((Item)Container.DataItem).HasChildren ? "dropdown" : "link" %>" class="<%# ((Item)Container.DataItem).HasChildren ? "dropdown" : "link" %>">
<a href='<%# GetLink(((Item)Container.DataItem),"MenuLink") %>'><%#((Item)Container.DataItem)["MenuTitle"] %></a>
</li>
</ItemTemplate>
<FooterTemplate></ul></FooterTemplate>
</asp:Repeater>
TopMenu .cs code:
public partial class TopMenu
{
private ID _homeId = new ID("{110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9}");
protected void Page_Load(object sender, EventArgs e)
{
RightSide.DataSource = GetMultiList("Right side", RootItem);
RightSide.DataBind();
***HERE I NEED TO MAKE THE CHECK.
So the code below should only run if the postback came from the topmenu***
var sectionItem = GetAncestorOrDefault(CurrentItem);
Sitecore.Data.Database context = Sitecore.Context.Database;
Sitecore.Data.Items.Item homeItem = context.GetItem("/sitecore/content/home");
List<Item> items = new List<Item>();
Sitecore.Data.Fields.MultilistField multilistField = homeItem.Fields["Right Side"];
foreach (string id in multilistField)
{
Sitecore.Data.Items.Item multiItem = Sitecore.Context.Database.Items.GetItem(id);
if (multiItem.HasChildren)
{
items.Add(multiItem);
}
}
foreach (Item item in items)
{
if (item.Name.Equals(sectionItem.Name))
{
hiddenAttr.Value = sectionItem.Name;
break;
}
else
{
hiddenAttr.Value = String.Empty;
}
}
}
}
I have tried with eventtarget but it is always null and also with hidden field which value is always "" in the codebehind. I am out of ideas...
I will post more code if needed.
Thanks in advance!
Örvar
You are overwriting all values in postback. Wrap the code in if(!IsPostBack){} for repeater data binding:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
RightSide.DataSource = GetMultiList("Right side", RootItem);
RightSide.DataBind();
}
else
{
// ***HERE I NEED TO MAKE THE CHECK.
// So the code below should only run if the postback came from the topmenu***
var sectionItem = GetAncestorOrDefault(CurrentItem);
Sitecore.Data.Database context = Sitecore.Context.Database;
Sitecore.Data.Items.Item homeItem = context.GetItem("/sitecore/content/home");
List<Item> items = new List<Item>();
Sitecore.Data.Fields.MultilistField multilistField = homeItem.Fields["Right Side"];
foreach (string id in multilistField)
{
Sitecore.Data.Items.Item multiItem = Sitecore.Context.Database.Items.GetItem(id);
if (multiItem.HasChildren)
{
items.Add(multiItem);
}
}
foreach (Item item in items)
{
if (item.Name.Equals(sectionItem.Name))
{
hiddenAttr.Value = sectionItem.Name;
break;
}
else
{
hiddenAttr.Value = String.Empty;
}
}
}
}
Also I would suggest using a query parameter in tag. If the href is
"/MyContent/MyPgae1"
you can change it to
"/MyContent/MyPgae1?s=r"
and in the postback :
if (!IsPostBack)
{
RightSide.DataSource = GetMultiList("Right side", RootItem);
RightSide.DataBind();
}
else
{
if(Request.QueryString["s"] == "r")
{
//request is from rightmenu
}

Server side variable in client side custom validator

I have a custom validator on a page:
<asp:CustomValidator ID="CustomValidator2" runat="server"
ControlToValidate="ddlProposer" ErrorMessage="Please select some values."
Display="Dynamic" onservervalidate="CustomValidator2_ServerValidate"
ClientValidationFunction="CustomValidator2_ClientValidate">
</asp:CustomValidator>
It must be valid, when a server-side list is not empty (or: the ListCount variable > 0). This list may change after the page has been loaded (via buttons on update panel):
public partial class Pages_Application_Application : System.Web.UI.Page
{
protected List<IdValue> ProposersList
{
get
{
if (ViewState["proposersList"] == null)
ViewState["proposersList"] = new List<IdValue>();
return ViewState["proposersList"] as List<IdValue>;
}
set
{
ViewState["proposersList"] = value;
}
}
public int ListCount
{
get
{
return this.ProposersList.Count;
}
}
...
There is no problem with server-side validation:
protected void CustomValidator2_ServerValidate(object source, ServerValidateEventArgs args)
{
args.IsValid = this.ProposersList.Count > 0;
}
The problem is with client-side part. I've been trying something like this:
<script type="text/javascript">
function CustomValidator2_ClientValidate(source, arguments) {
var serverVariable = <%= ListCount %>;
alert(serverVariable);
arguments.IsValid = serverVariable > 0;
}
</script>
however, it fires only on first page load, and the ListCount variable is always 0 (so does the serverVariable).
The question is: is there an easy-way to make it working? So the Javascript gets the current value of some server-side variable?
you can use hidden variable on the page level and by setting its value from server side and validate on client side.
<input type="hidden" id="ListCount" runat="server" value="0" />
public partial class Pages_Application_Application : System.Web.UI.Page
{
protected List<IdValue> ProposersList
{
get
{
if (ViewState["proposersList"] == null)
ViewState["proposersList"] = new List<IdValue>();
return ViewState["proposersList"] as List<IdValue>;
}
set
{
ViewState["proposersList"] = value;
ListCount=value;
}
}
public int ListCount
{
get
{
return this.ProposersList.Count;
}
}
<script type="text/javascript">
function CustomValidator2_ClientValidate(source, arguments) {
var count= document.getElementById("ListCount").value;
alert(count);
arguments.IsValid = count > 0;
}
You'll have to do it in plain javascript, and there is no sens of getting the server side variable since it won't be up to date at the moment client validation will be done.
What you need is pass your ddl html element to your CustomValidator2_ClientValidate function and check if it contains option html elements, that should do the trick.

How to dynamically create and add textbox to a placeholder using AJAX?

I'm trying to create text box dynamically. so I cal it through the AJAX function.
This is my code:
Ajax function
function ChangedAdults(noofAdults) {
alert(noofAdults.value);
$.ajax({
type: 'POST',
dataType: 'json',
url: "/FlightBooking.aspx/Adults",
data: "{noOfAdults:'" + noofAdults.value + "'}",
contentType: "application/json; charset=utf-8",
success: function (result) {
$("#AdultsList").html(result.d);
},
error: function (xhr, ajaxOptions, thrownError) {
alert(xhr.status);
alert(thrownError);
}
});
}
code behind
[WebMethod]
public static string Adults(int noOfAdults)
{
FlightBooking obj = new FlightBooking();
obj.CreateAdultsList(noOfAdults);
string test= "";
return test.ToString();
}
private void CreateAdultsList(int noOfAdults)
{
int n = noOfAdults;
for (int i = 0; i < n; i++)
{
TextBox MyTextBox = new TextBox();
MyTextBox.ID = "tb" + "" + i;
AdultsListPlaceholder.Controls.Add(MyTextBox); //error coming here
AdultsListPlaceholder.Controls.Add(new LiteralControl("<br />"));
}
}
But I receive an error:
Object reference not set to an instance of an object
What could cause this problem?
You can not dynamically add controls to a page using JQuery AJAX. Please get a good understanding of asp.net page lifecycle
In short this is how asp.net pages work.
Browswer sends request to server. i.e. http://localhost/test.aspx
Server creates a object for the page class. In this case the class is Test
The object renders the page. That means it converts the Controls of test.aspx to HTML which browsers can understand.
Server sends the rendered HTML back to Browser and destroys the object.
Browser displays the page.
So the server creates a new object every time it receives a page request.
However when a call to WebMethods is made using AJAX, no page object is created. This is why Webmethods have to be static.
I can see you are trying to create a object yourself and add the dynamic controls to that object. But this object is not related to the content displayed in the browser. So, adding controls to this object won't change anything that's displayed in the browser. For that to happen you have to post the whole page back. And if you return the rendered output of the object you created with Response.Write, that will return the HTML version of the whole page. Which is basically same as a PostBack
However, you can achieve AJAX based dynamic control rendering using UpdatePanel. Below is one way to do it
ASPX page
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
<asp:Button ID="btnCreate" runat="server" Text="Create" OnClick="btnCreate_Click" />
</ContentTemplate>
</asp:UpdatePanel>
<asp:Button ID="btnRead" runat="server" Text="Read" OnClick="btnRead_Click" />
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
</form>
Code Behind
protected int NumberOfControls
{
get { return Convert.ToInt32(Session["noCon"]); }
set { Session["noCon"] = value.ToString(); }
}
private void Page_Init(object sender, System.EventArgs e)
{
if (!Page.IsPostBack)
//Initiate the counter of dynamically added controls
this.NumberOfControls = 0;
else
//Controls must be repeatedly be created on postback
this.createControls();
}
private void Page_Load(object sender, System.EventArgs e)
{
}
protected void btnCreate_Click(object sender, EventArgs e)
{
TextBox tbx = new TextBox();
tbx.ID = "txtData"+NumberOfControls;
NumberOfControls++;
PlaceHolder1.Controls.Add(tbx);
}
protected void btnRead_Click(object sender, EventArgs e)
{
int count = this.NumberOfControls;
for (int i = 0; i < count; i++)
{
TextBox tx = (TextBox)PlaceHolder1.FindControl("txtData" + i.ToString());
//Add the Controls to the container of your choice
Label1.Text += tx.Text + ",";
}
}
private void createControls()
{
int count = this.NumberOfControls;
for (int i = 0; i < count; i++)
{
TextBox tx = new TextBox();
tx.ID = "txtData" + i.ToString();
//Add the Controls to the container of your choice
PlaceHolder1.Controls.Add(tx);
}
}
Hope this helps.
You're mixing your paradigms. What would you expect this code to do? You can render controls in response to an AJAX call, but you must then manually insert the processed HTML into the DOM.
Call server using AJAX
Instantiate a dummy page container
Render server control
Return markup
Insert into DOM
Or, you can add new controls in response to a server event via a full postback or an async postback (e.g. an UpdatePanel).
In asp.net you can not create server control from jQuery or java-script.
Though you can call web-method from jQuery but you can't add any control from web method.
More details
Add new ASP.NEt server controls with jQuery?
One of the idea it to create textbox is to create html textbox
<input type="text" id="text1" ></input>
And post your value through jQuery ajax for manipulation.
Edit 1
Other way is to create all the controls at page load (If you know the maximum number)
Hide them initially
Show one by one on button click
And get the value on the server after postback.
Example:
add text to an asp.net textbox control with jQuery
AdultsListPlaceholder is null, you need to override its onload function to create children of this control.
e.g.
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
CreateAdultsList(5);
}

Categories