Holding on to data passed from page to page - WP7 and C# - c#

I'm creating a WP7 application using C#, and I require to pass data from one page to the other.
I found solutions on SO, but I'm still running into problems.
On 'Page 1', I wish to display a list, that can be populated by the user, using input from 'Page 2'.
I used the following statement in 'Page 2' while navigating back to 'Page 1': NavigationService.Navigate(new Uri("/MainPage.xaml?text="+WhoBox.Text, UriKind.Relative));
WhoBox is a Text Box.
On 'Page 1', I have the following:
protected override void OnNavigateTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if (NavigationContext.QueryString.ContainsKey("text"))
ListBlock.Text = ListBlock.Text + NavigationContext.QueryString["text"];
}
Now, this works, but in a limited fashion. If I try adding something from 'Page 2' for a second time, it replaces what is present in ListBlock (which is a Text Block) with the newly added text instead of appending it.
Shouldn't ListBlock.Text = ListBlock.Text + NavigationContext.QueryString["text"]; cause the new text to be appended, rather than to entirely replace the older text?
EDIT: I may have found the solution. For whatever reason, no changes in the XAML or .cs file are reflected when I run the program using F5. Am I doing something wrong? For example, even if I delete a button, it still appears when I Debug (F5) the program. Is there some setting I need to change? Or am I supposed to use some other command? I'm relatively new to Visual Studio, so please excuse me.

The problem is that the moment you again leave your page 1 it is basically disposed of. Meaning any text that was set in the Listbox is also removed. You will , in other words, need to save the state of that page before leaving it.
There several possibilites here:
Use AppSettings (see Windows phone 7 config / appSettings? )
Write the state to a local database
Do a quick'n dirty fix by saving the Text in the App.xaml.cs which all pages can work with: First you need to create the application-wide variable (and initialize if needed) inside the app.xaml.cs file. For example:
public partial class App : Application
{ public string myText;
From now on you can reach any App-variable through the Application.Current object. So if you need to access bigVar from some page in you application (e.g. MainPage) you simply type:
string Text = (Application.Current as App).myText;

Consider using sessions and datatable: Storing and retrieving datatable from session

Related

asp.net/C# control - store value from previous page load

control (eg label) changes value when page loads.
before page load, label value is "x"
proceed to load page naturally x is lost at this point, so what is a simple way to store the value from the previous page
load?
It sounds like what you want is a history of previous states of the page, or at least just one previous value. I can suggest a way to do this, but with a caveat: Don't overuse it. You can persist data between posts in ViewState but that data gets written to the page itself. That way when the users posts the form, they're also posting that data back. (More at the end.)
Here's a simple example. First, define some class that contains all of the additional state you want to store:
[Serializable]
public class PageState
{
public string MyLabelPreviousText {get;set;}
}
Then in your code behind:
public partial class MainPage : System.Web.UI.Page
{
private PageState _pageState;
protected void Page_Load(object source, EventArgs e)
{
_pageState = ViewState["pageState"] as PageState ?? new PageState();
_pageState.MyLabelPreviousText = MyLabel.Text;
}
protected void Page_PreRender(object sender, EventArgs e)
{
ViewState["pageState"] = _pageState;
}
When you load the page, you're checking to see if you've already saved your class (in this case called PageState) to the ViewState. If you haven't, you create a new one.
In the PreRender event, after you're done updating the page, you're updating that class with the text of your label and then saving the whole thing to ViewState again. That way the next time the page loads you can retrieve it again.
I'm not sure at which point you want to save the previous text of your label. In this example it's saving the text during the Load event. That way if the text is changed at any point from then on, the value you have saved is the original text of the label. The details may vary depending on what you're trying to do, but this pattern lets you save that sort of custom data without using Session and piling up data like this in memory.
I mentioned not overusing it. If you save some labels, controls, and other data, ViewState probably won't get too large. ASP.NET is already putting the state of every server control there anyway. But if you go really crazy with it then ViewState can get huge. All of that data gets written to the page, and all of it gets posted back to the server with each postback.
It's probably not a huge concern, but be mindful of it. Use Chrome dev tools, Fiddler, or even just inspect your page source to see if that data is getting so large that it might impact performance.
For anyone who isn't familiar, ViewState looks like this in the HTML source:
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE"
value="/wEPDwULLTEyMzgxNzgyNDIPZBYCZg9kFgICAQ9kFggCAQ9kFgJmD2QWAgIBD2QWAmYPZBYMA
... etc.
As you can see, it's actually a hidden form input. ASP.NET is placing all of the details of the page's controls in the form so that when you post the form, it can piece all of that together and make sure that the page looks the same after postbacks. That's the reason why when we set up a lot of controls the first time we check if(!IsPostBack()). If it is a postback then we don't need to populate the dropdowns, etc. all over again. They are restored from that ViewState data.
This approach is functionally the same as adding an additional hidden input as suggested in one comment. The difference is that you're using an existing hidden input (viewstate) and if you need to save multiple values you're just making them properties of a class instead of adding more and more hidden inputs.
I'm not sure if this is what you mean without any code samples but I know from memory that in ASP.NET you can access the previous page property like so:
Page lastPage = currentPage.PreviousPage
Which returns the entire Page object. Assuming your label is defined like so:
<asp:label id="myLabel" runat="server" />
Then you can access the text property with:
Label myLabel = lastPage.FindControl("myLabel") as Label;
lastPageVal = myLabel.Text
So ensure that lastPageVal is a static variable, then it will also persist throughout pages.

How does FindViewById() work?

I'm new in mobile app development. I'm using Xamarin to develop Android applications. In the hello world app in the OnCreate method I see the following code:
Button button = FindViewById<Button>(Resource.Id.MyButton);
So I'm trying to create my own button the same way. I create the button in the designer and inside OnCreate method put the line:
Button myOwnBtn = FindViewById<Button>(Resource.Id.MyOwnBtn);
That gives me an error that there is no MyOwnBtn. Then I'm looking the code of Id class and see there a line like:
public const int MyButton=2123344112;
If I put there the line:
public const int MyOwnBtn=2123344113;
Everything works fine. But as I understand it should be generated automatically or it will be a little bit difficult to put there a unique number for each control.
Can anybody tell me what I am doing wrong? And how does FindViewById() work?
You have to give the id MyOwnBtn to the Button that you created in the designer.
findViewById is a method of the View class and it looks for a child view having the id that you provided in the argument.
From official documentation:
Look for a child view with the given id. If this view has the given id, return this view.
MyButton id is not a const value, It will change every launch.
The Activity or ViewGroup's findViewById() method returns a view that already has an id. The findViewById() method should be used in conjunction with XML layouts to provide a reference to the View that was defined in the XML file.
Edit: Not entirely sure if my answer is relevant to Xamarin. I apologize if I have mislead people, I am referring to Java Android application development.
When you declare a button in your .xml file, you should set an id for it (Usually it is done using string.xml file). After that, R.java will be updated automatically and set a number to your declared id and you can access your button by that id like what you have done.
It will try to find it from the XML file that you inflate. So make sure you inflate the correct xml file. This code inflates the xml:
SetContentView (Resource.Layout.MainLayout);
Even if you got the correct id created in a xml file, if you don't inflate it first, the system won't be able to find that view since it is not inflated.

ASP.Net passing textfield value to a label on a different web page

I have a page called webForm1, this page contains a textfield, when a user enters a value, I want the value to show up in a label on webForm2, when I do that, I am getting an error:
Label1 is inaccessible due to its protection level
This is what I am doing in webForm1
webForm2 webform = new webForm2();
webform.Label = textBox1.Text;
Response.redirect("~/webForm2.aspx");
but the above is not working, I am new to programming and not familiar with classes and complicated programming, what is the easiest way to get the value of the textbox in the label?
Thank you.
You can't instantiate the page class (webForm2) in your current page. You'll have to pass the value in another way to the second page and then bind the label. As Jason P says, the ASP.NET framework instantiates the webForm2 page for you, you can't do it yourself.
If the data is not sensitive, use the Query String:
Response.Redirect("~/webForm2.aspx?label=" + textBox1.Text);
This will redirect the user to a page with the url of whatever.com/webForm2.aspx?label=whatevervalue. On the second page, you can pull the text from the query string and bind it to the label:
public void Page_Load(object sender, EventArgs e)
{
Label.Text = Request.QueryString["label"].ToString();
}
Unlike WinForms, you don't instantiate the next form like that. Essentially, your first two lines are incorrect for WebForms. The third line is where you want to focus your attention. You redirect the user to the second form, allowing the framework to take care of instantiating it.
This is because WebForms, despite being "forms", is still an HTTP web application and does everything through requests and responses. By issuing a redirect you are telling the client to abandon the current page and make a new request for the specified page.
There are a number of ways to send a value to this next page. You can store it in some persisted medium (such as a database), you can use session state, etc. Probably the simplest approach at the moment would be to include it on the query string:
Response.Redirect("~/webForm2.aspx?label=" + textBox1.Text);
Then in the next page you'd get the string from:
Request.QueryString["label"]
You may want to URL-encode the text value first, I don't know if Redirect() does that for you. Also keep in mind that this isn't a "secure" transfer of data from one page to the next, because the client has full access to modify values in the URL. So if this is in any way sensitive data then you'll want to look into other approaches. (Keep in mind that "sensitive" could be a relative term... The information itself might not be sensitive but you might be doing system-sensitive things with it on the next page, which we can't know from the code posted.)

Saving webControls in the Session object

I have a panel (pnlPanel) with lots of controls like Textboxes and DropDownLists. I want them to be persistent when the user gets back to the page, so i tried this:
/*i have saved the panel like this
Session["testPanel"] = pnlTest;
*/
protected void Page_Load(object sender, EventArgs e)
{
if (Session["testPanel"] != null)
{
panel = Session["testPanel"] as Panel;
}
}
But its not working. Is it possible? The reason why i want to do this is because overhead is not a problem, and i want to cut down on coding time.
I've never tried this myself, but this seems to me to be an extra-ordinarily bad idea. Without testing it, my guess would be that this will create a ton of ViewState problems. Even if you could maintain the ViewState, attempting to keep this control over multiple page loads would be dangerous at best.
My recommendation would be to have a common object that holds the properties of the panel you want and just build a method into one of the early events to prepopulate a new panel with those properties.
Without knowing the entire reason for doing something like this, you should have a look at output caching directives. You would be best served by pulling the content out of the panel and into a user control. Then setting output caching on control, using VaryByCustom so you can use the user name or some other unique identifier to separate by user.
http://msdn.microsoft.com/en-us/library/hdxfb6cy.aspx and
http://msdn.microsoft.com/en-us/library/system.web.httpapplication.getvarybycustomstring.aspx
Using session and/or caching will be problematic if you are in a webfarm scenario. Cache is scoped to the application instance, so another server in the web farm will not have access to it.
Some other side effects of something like this include issues with viewstate.
What you try to do here is to cache the Panel but this is not the way. The panel as you save it is a running object on the memory and can not be saved as it is. You need to convert it to html string and save and cache this string. So near the Panel you place a literal, then you render the Panel and save it on session, and then actually you display the text from this render.
if(Session["testPanel"] == null)
{
TextWriter stringWriter = new StringWriter();
HtmlTextWriter renderOnMe = new HtmlTextWriter(stringWriter);
// render and get the actually html of this dom tree
testPanel.RenderControl(renderOnMe);
// save it as cache
Session["testPanel"] = stringWriter.ToString();
}
// render the result on a literal
cLiteralID.Text = Session["testPanel"];
// hide the panel because I have render it on literal.
testPanel.Visible = false;
Need some tests as is it. I use some similar code for custom control and custom cache, never save on session this amount of data.
First Approach
protected void Page_Load(object sender, EventArgs e)
{
if (ViewState["panel"] != null)
{
panel = ViewState["panel"] as Panel;
}
}
In this approach your ViewState objects were different. You may be getting some null values once the ViewState["panel"] is given the control memory and the object is being accessed in the impression that the Session was Session["panel"]
Second Approach
Save the Complete panel HTML in database and access it on the form load by keeping the function under IsPostBack.
Now with the continuity of approach - 2 assign the value to your session object.
this.Controls.Add(new LiteralControl("Your HTML"));
Third Approach
You can use File system. Save the div in your file and access the file at runtime.
Hope this may help you.
EDIT - 1 => Added code for second approach
I had a similar problem. I tried to save an object to the View State that stored a Panel and I got an error message telling me that Panels aren't serializable. You could try using a SerializationSurrogate.
https://msdn.microsoft.com/en-us/library/system.runtime.serialization.iserializationsurrogate(v=vs.110).aspx

Can't find the function body in ASP.NET

I recently started working on a project that has been in development for some time now. The problem is this - in the web site page, a have a frame (amongst 4 others) in a frameset which contains the SVG map object (the whole site is GIS based). Also, in the same frame, there is a icon for opening the form in which user can choose a number of filters, and after he presses a button, the map refreshes and the area of influence around some key points on the map are drawn.
What i need to do is to open that form in a new (popup) window and not in the same frame where the map is. I did that this way:
onclick="window.open('zi.aspx','form1','width=700,height=500,left=350,top=100')"
This works fine. But then, when i enter the filters and hit Generate button, i get this error:
'parent.frames.map' is null or not an object
with the reference to zi.aspx. Now i know that this error is because i changed the form from opening in the same frame as map to opening it in a popup window, but i just can't find anywhere in the code where can i modify it. Before my changes, the code was just this:
onclick="showZi();"
and that is the function i can't find anywhere. Any ideas? How can i make this work, to make a map with filters drawn after the user has chosen appropriate ones from the popup window form? I should mention that this image link is in the ASP.NET table, with standard runat="server" command.
Okay, so you're opening a new window from javascript. Your problem is that you're trying to access the parent window by using the 'window.parent' property. This is wrong, you'll need to instead use 'window.opener' property. E.g.:
window.opener.frames.map

Categories