I am creating a custom user control that will act as a search feature. I want to easily be able to add this to multiple pages without having to modify much code.
I thought the best method to do this would be to create a simple user control that I can inject anywhere with one line of code and then have this control postback to a different URL. So wherever the search function is, it will always post back to the same page. My control looks like this:
<asp:TextBox ID="searchTextBox" runat="server" MaxLength="350"></asp:TextBox>
<asp:Button ID="submit" runat="server" Text="Search" PostBackUrl="~/myPostBackPage.aspx" />
myPostBackPage.aspx.cs looks like this, but it isn't grabbing the text.
protected void Page_Load(object sender, EventArgs e)
{
content.InnerHtml = ((TextBox)PreviousPage.FindControl("searchTextBox")).Text;
}
But it isn't pulling anything from the searchTextBox field and I get:
Object reference not set to an instance of an object.
Is there a better way to do this or how should I fix my code? Thanks!
I don't know where the TextBox is declared, if you for example use MasterPages the NamingContainer of it would be the ContentPlaceHolder of the master instead of the Page. Therefore just cast the PreviousPage property to the correct type:
YourPageType page = PreviousPage as YourPageType;
if(page != null)
{
content.InnerHtml = page.SearchText;
}
You have to provide a public property since the TextBox is protected(best-practise anyway):
public string SearchText
{
get { return searchTextBox.Text; }
}
I tested your code and PreviousPage is null. Try switch to Page.
Related
I am working with the web application which I have only binaries. The application allows developing extension by providing internals to the derived classes.
What I would like to achieve is to add additional functionality to the existing aspx page. Because I can’t replicate and modify corresponding code I thought about developing a UserControl and modify markup of the discussed aspx page to include that control.
Until now I was successful. The control appears on the page and triggers server event handlers. It also has access to the application internal data. What I need now is to programmatically manipulate some of the original page elements from that UserControl server side.
I know that this is not the purpose of User Controls and they should not to have any knowledge about parrent page elements. However, this is as far as I know the only way to include some of the custom functionality to the existing page.
Before I asked this question I have spent a good amount of time for researching avaiable solutions.
Please, could you suggest the best possible way of referencing those elemnent from the User Control at server side?
Below is a simplified code representation of what I have done so far
The existing aspx page:
// SOME CONTENT OF THE ORGINAL PAGE
<%# Register TagPrefix="uc" TagName="MyControl" Src="~/usercontrols/MyControl.ascx" %>
// SOME CONTENT OF THE ORGINAL PAGE
<uc:MyControl ID="pnlMyControl" runat="server"></uc:MyControl>
// SOME CONTENT OF THE ORGINAL PAGE
My User Control:
public partial class MyControl : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
//DO SOMETHING HAVING ACCESS TO INTERNAL DATA
}
protected void lnkTest_Click(object sender, EventArgs e)
{
//DO SOMETHING HAVING ACCESS TO INTERNAL DATA
}
}
I've done something similar, though I've done it for variables rather than controls so I shall attempt to adapt it here.
I used properties to achieve this, working with:
<%# Register TagPrefix="uc" TagName="MyControl" Src="~/usercontrols/MyControl.ascx" %>
<uc:MyControl ID="pnlMyControl" runat="server" />
In the UserControl you do something like:
private string _myTextBox = new TextBox();
public string myTextBox
{
get
{
return _myTextBox;
}
set
{
_myTextBox = value;
}
}
Then in the parent page, you can set these properties; for example:
protected void Page_Load(object sender, EventArgs e)
{
pnlMyControl.myTextBox = MyParentTextBox;
}
Also, you may find this useful; you can directly fire methods on the parent from the user control using this:
this.Page.GetType().InvokeMember("MyMethodName", System.Reflection.BindingFlags.InvokeMethod, null, this.Page, new object[] { });
I hope that helps.
My web site uses a master page, where I've placed two controls, a TextBox and an ImageButton, they are intended to be viewed and accessible on all content sites. Here's the aspx code in Site.Master:
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:ImageButton ID="ImageBtn" runat="server" ImageUrl="~/Image.png"
PostBackUrl="~/Result.aspx"></asp:ImageButton>
Clicking the button should redirect the visitor to Result.aspx, which it does.
Result.aspx.cs has the following in the Page_Load event:
protected void Page_Load(object sender, EventArgs e)
{
TextBox txbx = this.Master.FindControl("TextBox1") as TextBox;
if (txbx != null)
{
Label1.Text = "Value: " + txbx.Text;
}
else
{
Label1.Text = "TextBox seems to be null";
}
}
The weird behavior appears when the image button is clicked the first time. The visitor gets this information from the page "Value: " (i.e an empty string ""), even though a value was entered in TextBox1. The subsequent clicks presents the value(s) correctly, e.g "Value: SomeText".
Why doesn't the value "come along" the first time?
Is there a better way to ensure that?
The visitor is redirected to Result.aspx AND
that the value is "registered" and can be handled in Result.aspx.cs AND
that a user will be redirected, if Result.aspx is entered without the use of the image buttons PostBackURL
I've tried IsPostBack but it seems to behave strangely when using a master page as previous page ...
Very thankful for an answer!
Sincerely,
Mr Kay
If you are using PostBackURL on your ImageButton on the master page and come from another page you must use:
PreviousPage.Master.FindControl("TextBox1") as TextBox;
If you are on the PostBackURL page and click your ImageButton, you need to use
Master.FinControl("TextBox1") as TextBox;
(PreviousPage would be null in this case)
you could use something like this:
var txbx = PreviousPage == null ?
Master.FindControl("TextBox1") as TextBox :
PreviousPage.Master.FindControl("TextBox1") as TextBox;
See: http://msdn.microsoft.com/en-us/library/system.web.ui.page.previouspage(v=vs.100).aspx
at the Remarks section.
Since you know your form is derived from the master... have you tried explicit type-casting to get at it??? such as
TextBox txbx = ((site.Master)this).Textbox1;
then do whatever you want from there... It's been a while since I've been into asp.net, but remember doing something similar in one of my older apps.
i have a page where on click of a button, a javascript function runs. It then aggregates some data and places the data on a hidden field in this page. It then opens a new window. This new window picks up this aggregated data like so :-
$('#accepted').val(window.opener.$('#accepted').val());
where accepted is the hidden field in both parent and child window (no runat="server" was used). The issue now is that i require this data to databind two grids. Currently I've done a doPostback on both grids, but what i really want to do is doPostback for the form once and handle the databinding the PageLoad event. So two questions :-
1) How do i doPostback the form?
2) How do i do this while still being able to differentiate from the actual form submission?
To post the form you should just be able to add a call to __doPostback in your javascript, after the accepted field is set. You can use the EventTarget and EventArgument parameters of the __doPostback to control the binding in your grid.
So, you could put this in your js:
__doPostback('rebindGrid', '');
and then this in your page load event:
if (Request.Form["__EVENTTARGET"] == "rebindGrid")
{
//....Do so stuff
}
In order to tie it in more directly with the postback model I wrap mine with some C#
C# Extension Method
public static string GetPostBackLink (this Control c, string argument = "") {
return c.Page.ClientScript.GetPostBackEventReference(ctl, argument, true) + ";";
}
ASPX
<asp:LinkButton id="lnkDoThis" runat="server" onclick="lnkDoThis_Click"
style="display: none;"></asp:LinkButton>
<asp:HiddenField id="hdnParamHolder" runat="server" />
JS
function DoSomething(param) {
$("[id$='hdnDealTemp']").val(param);
<%= lnkDoThis.GetPostBackLink() %>
}
CodeBehind
protected void lnkDoThis_Click (object sender, EventArgs e) {
var myParam = hdnParamHolder.Value;
// Do server actions here
}
As for the opening in a second window ... I am not sure I follow when you want this to happen? If it is after the postback you will need to read from the hdnParamHolder control when the page reloads.
I have a website that returns search results from Twitter, written in C# ASP.NET. The search works very well.
When the user sees the results I want them to also have a 'Next Page' type hyperlink that will perform the search from the last previous result onwards (using Twitter's next_page data).
How can I preserve properties so that when a link is clicked it will run the search again with different parameters for the next results? I cannot use Form as there is one Form on the page already and MS limits to one Form per page (for runat="server").
Please help, this is driving me nuts.
PS I thought of including code, but not sure which bit to include, as it has more to do with how ASP.NET works as much as how my own coding is.
There's a hundred different ways to solve this problem. The ASP.NET infrastructure includes something called ViewState, which allows the page and its controls to persist arbitrary data and objects across page views.
There is a single <form>, but you can have an unlimited number of links and buttons which submit the form in different ways - each one can trigger its own method when the page posts back.
A simple way to leverage this in your case is to store the page parameter on the "next page" link. This is a very simple example that assumes you only need to know the page number, but it gets the point across:
<asp:LinkButton runat="server" ID="next_page" Text="Next Page" OnClick="NextPage_Click" />
...
void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
{
LoadData(0);
}
}
void LoadData(int page)
{
//pull page of data from twitter & show on page
next_page.CommandArgument = (page+1).ToString();
}
void NextPage_Click(object sender, EventArgs e)
{
int page = int.Parse(((LinkButton)sender).CommandArgument);
LoadData(page);
}
In this example we set the CommandArgument property of the LinkButton to the page index we want. The LinkButton triggers the NextPage_Click method to be called, and ASP.NET's ViewState infrastructure allows the CommandArgument value is persisted.
There are two easy ways to do it:
Include a parameter in the url that is the href of the Next hyperlink, the url could look something like this:
http://mysite.com/myWebPage.aspx?currentPage=1
you can then access that parameter from the querystring in your code behind.
You can also save it to Session:
Session["currentPage"] = 1;
then upon postback you can check for it:
int currentPage = 0;
if (Session["currentPage"] != null)
int.TryParse(Session["currentPage"].ToString(), out currentPage);
with the Session it will automatically expire depending on your IIS setup, whereas using the querystring option it doesn't expire (although the user can mess with it so you will have to validate it before using it).
Have your properties save their values to the viewstate.
Something like this:
public int PageNumber
{
get
{
object value == this.ViewState["PageNumber"];
if(value != null)
{
return (int)value;
}
else
{
return 1;
}
}
set
{
this.ViewState["PageNumber"] = value;
}
}
We are trying here to localize our user control basically we want to be able to do something like this :
<in:Banner runat="server" ID="banners" Lang="fr" />
The way we do this is by page level and send it to master that then send it to the control:
protected void Page_Load(object sender, EventArgs e)
{
Master.Lang = "FR";
}
Then in the MasterPage.master we do something like this :
<in:Banner runat="server" ID="banners" Lang="<%= Lang %>" />
The masterpage has a public proprety named Lang.
In the control we have set a field that contains the default language and a proprety (Lang) that set the language. It seems that whatever we do, the current language is not sent from the page to the usercontrol... any help?
Not exactly like that, but you can consider the content page like a control in the master page, so its likely that the page load of the page is executing before the page load of that user control.
Regardless of the above, why not set the ui culture to the asp.net thread (probably from the global.asax), and using that from the control.
Another alternative is to have a separate class where you hold the current language, and expose a change event ... that way you can make sure to use the right language even if the load is done differently --- or there is a change language event later.
You can access it in code-behind of the MasterPage like this
public void SetLanguage(string language)
{
banners.Lang = language; //banners is an ID reference to your user control.
}
Or in your markup I think you can do it like this
<in:Banner runat="server" ID="banners" Lang='<%# Bind("Lang") %>' />
I should mention that Bind works in .Net 2.0 and up.