Null Reference when Passing Parameter with Navigating Pages [WP8.1] - c#

I don't understand why or what I'm doing wrong, but I get a null reference exception when the follow code is executed in my Windows Phone 8.1 application:
First, the application navigates and passes the selectedStation to the next page...
Code from the MainPage:
// When an item is selected, go to the next page and pass info
private void listBoxStations_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
// Get the selected station item
CompleteStation selectedStation = (CompleteStation)this.listBoxStations.SelectedItem;
this.Frame.Navigate(typeof(StationInformationPage), selectedStation);
// Make sure we set the selected index to -1 after item is selected so
// when we come back to page, no items are selected
this.listBoxStations.SelectedIndex = -1;
}
Here is the code that is getting the null error in the next page:
private CompleteStation station;
protected override void OnNavigatedTo(NavigationEventArgs e)
{
this.navigationHelper.OnNavigatedTo(e);
this.station = (CompleteStation)e.Parameter;
AddInformation();
}
private void AddInformation()
{
this.txtStationTitle.Text = station.StationName;
// Add more information here
}
The error is specifically happening when I try to change the txtStationTile.Text to station.StationName.
If I take out the code that changes the textbox, and I step through the program, it shows that the station variable is not actually null by the end of the OnNavigatedTo method...
Any help would be greatly appreciated!
-Johan

It seems that it's not the station that's null, but the this.txtStationTitle.
You're doing everything in OnNavigatedTo while the page (XAML) including the TextBlock you're trying to change is not completely loaded, so the TextBlock is null and when you try to do this.txtStationTitle.Text, you get a NullReferenceException.
However, if you called AddInformation in Loaded event handler of the Page, then you'd be sure that the page is fully loaded and TextBlock would not be null anymore.
public SomePage()
{
this.InitializeComponent();
this.Loaded += SomePage_Loaded;
}
void SomePage_Loaded(object sender, RoutedEventArgs e)
{
AddInformation();
}
This type of exception is usually very easy to debug. Putting a breakpoint on the following line:
this.txtStationTitle.Text = station.StationName;
and examining this.txtStationTitle and station would make it really simple to find out what exactly is null.

Related

Accessing DOM from application_error

I have a custom error handler for an asp.net site.
void Application_Error(object sender, EventArgs e)
{
// Code that runs when an unhandled error occurs
//if (System.Configuration.ConfigurationManager.AppSettings["ProductionMode"] == "Yes")
#if (!DEBUG)
Server.Transfer("~\\GlobalExceptionHandler.aspx");
#endif
}
It works fine and dandy when retrieving exception information cause it'll just snag Server.getLastException() and email it on to me for review
However, I have some TextBoxes on the page and I'd like to send the value of those textboxes along with the email. Maybe it's not quite the DOM I'm looking for access to but instead those posted variables.
I tried looking at HttpContext.Current.Request.Form but it showed no keys.
So Does anyone know how to access the formvalues when globally catching an exception?
Accessing the Form Values
To access the form values in Global.Application_Error, you can simply use HttpContext.Current.Request.Form.
Here is a proof of concept, where a page immediately throws an exception on post(back) to hit the application error handler:
void Application_Error(object sender, EventArgs e)
{
var test = HttpContext.Current.Request.Form;
}
Setting a breakpoint on the assignment to test, then stepping over it (with F10) when it is hit, you can see that test is indeed set to the post(back)'s form-values collection.
Accessing the Postback Control Values
Alternatively, you can access the postback control values by adding them to the session on postback, for example...
// ************code behind
protected void TextBox1_TextChanged(object sender, EventArgs e)
{
Session["TextBox1"] = TextBox1.Text;
}
..., and accessing the session in the application error handler - for instance:
// ************Global.asax.cs
protected void Application_Error(object sender, EventArgs e)
{
// Use Session["TextBox1"].
}
A CodeVerge thread speaks to approach well - particularly Benson Yu's reply.

sending data from one sublayout to another in sitecore

I'm having a hard time building a filtering system in Sitecore 7.
I have 2 sublayouts, on the same level of the page.
Sublayout A is a sidebar that contains a list of checkboxes and has an event that populates a List with the selected values.
Sublayout B displays a set of items.
What I would like to do, is send the populated List from sublayout A to sublayout B in order to filter the items list based on what the user selected.
I was able to do this by passing the data through Session, but this is not an optimal way of handling that data.
I've tried defining a property for sublayout A and loading the list there, but I can't get the exact instance of sublayout A from sublayout B in order to read the populated property.
Also, trying to Page.FindControl("IdOfSomeElementFromSublayoutA") always returns null in Sublayout B. Even though I've casted Page as the .aspx page that contains both Sublayouts.
I'm using Sitecore 7 Update 2.
Thanks a lot for your time.
The best way to do this is by raising (and subscribing to) events using the Sitecore.Events.Event class. Your sidebar sublayout would raise an event using something like the following within a button's click event handler:
Sitecore.Events.Event.RaiseEvent("YourEventName", new YourEventArgsClass { Property = "SomeValue" });
then in the other sublayout you would need to have the following set up in order to handle the event:
public partial class YourOtherSublayout : System.Web.UI.UserControl
{
private System.EventHandler eventHandlerRef;
protected void Page_Load(object sender, EventArgs e)
{
eventHandlerRef = EventHandlerMethod;
Sitecore.Events.Event.Subscribe("YourEventName", eventHandlerRef);
}
protected void Page_Unload(object sender, EventArgs e)
{
if (eventHandlerRef != null)
{
Sitecore.Events.Event.Unsubscribe("YourEventName", eventHandlerRef);
}
}
private void EventHandlerMethod(object sender, EventArgs e)
{
if (e != null)
{
//do stuff here
}
}
}
Note: it is important to keep the Page_Unload code there otherwise you will see the EventHandler method being called multiple times.

document.getelementbyid not working inside loop/if

My problem is simple yet i cannot figure out why it's not working inside of if/loop. Here are some examples:
Working one:
private void button1_Click(object sender, EventArgs e)
{
webBrowser1.Document.GetElementById("login").SetAttribute("value", "something");
webBrowser1.Document.GetElementById("password").SetAttribute("value", "something");
}
Non working one:
if (webBrowser1.IsBusy == false)
{
webBrowser1.Document.GetElementById("login").SetAttribute("value", "something");
webBrowser1.Document.GetElementById("password").SetAttribute("value", "something");
}
No matter what the "if" statement is, it's not working. Also tried with "for", also tried to get it out of the loop of "for", i still get this error: "Object reference not set to an instance of an object."
I'm taking a guess here because of the limited information.
I think you are trying to modify the page right after setting the Url property. The webpage will not yet be loaded then so the controls you are getting are not available yet.
Try adding the code to the DocumentCompleted event of the WebBrowser. This event will be triggered right after the document is fully loaded and the elements will be available then.
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
var loginControl = webBrowser1.Document.GetElementById("login");
var passwordControl = webBrowser1.Document.GetElementById("password");
if (loginControl != null)
loginControl.SetAttribute("value", "something");
if (passwordControl != null)
passwordControl.SetAttribute("value", "something");
}
more: http://msdn.microsoft.com/en-us/library/system.windows.forms.webbrowser.documentcompleted.aspx
Update
Your assumption about IsBusy is not completely correct. It starts out false when nothing is loaded. settings the Url property will not immediately set it to true.
For an alternative you requested you could use the ReadyState property that will have the value of WebBrowserReadyState.Complete when loading is done. you could use the following example. Although i personally don't like it as there is the risk of endless loop when the page can't load for some reason. I would advise to use the DocumentCompleted if possible and i modified that example to correctly handle non-login pages as well.
while (webBrowser1.ReadyState != WebBrowserReadyState.Complete)
{
Thread.Sleep(0);
Application.DoEvents();
}

ASP.NET - Adding items to dropdownlist during construction

I have a web user control that holds three dropdownlists: One holds days, second holds months and the third one holds years. Days and months are static.But year items will change upon need to avoid entering wrong year. Let me first list here what I do in order, then i'll ask my question:
I have a private int yearSpan.
In private method PopulateYearList I say:
int year = DateTime.Now.Year;
int span = year - this.yearSpan;
for (int i = span; i <= year; i++)
{
ddlYears.Items.Add(i.ToString());//Here I get NullReferenceException
}
I've overriden the default constructor to receive yearSpan as an argument:
public DatePicker(int yearSpan)
{
this.yearSpan = yearSpan;
this.PopulateYearList();
}
Now, as you might have guessed in my PopulateYearList method I get NullReferenceException because I try to add an item to ddlYears that has not been constructed yet. What would you suggest to do to solve this?
don't call this.PopulateYearList in constructor, rather call it on Load event of user control.
Also I prefer you to not use constructor of your user control rather use public property as it can maintain its state.
e.g. in Page:
protected void Page_Load(object sender, EventArgs e)
{
UserControl1.TimeSpan = DateTime.Now.Year;
}
In UserControl:
protected void Page_PreRender(object sender, EventArgs e)
{
if(this.IsPostBack)
{
PopulateYearList()
}
}
As long as you don't make any change to that control from your parent page, any event after your controls are load , you can call this.PopulateYearList. I called it in PreRender event as if somebody changed the value from page it would be overriden by user control value at the end, thus I am sure my values are not tempered.
Let me know if I am missing something.
Ether call the PopulateYearList in the Page_Load of your usercontrol. Like this:
protected void Page_Load(object objSrc, EventArgs e)
{
if(this.IsPostBack)
PopulateYearList()
}
Or make the PopulateYearList public and call it on the page when you bind the page controls

ToolStripMenuItem click event should return a class

I had a DataGrid and a ContextMenuStrip in it. When I click SelectMenuStrip in a row I want the ClickEvent of the context menu to get all data in that row in a databean class and return that databean class, so that I can fill the data in another class-
All was fine I defined event as below
private CustomerDataBean toolStripMenuItem1_Click(object sender, EventArgs e)
{
CustomerDataBean custdatabean = null;
int rowno = tblcustomerdataview.CurrentCellAddress.Y;
custdatabean.Customerpk = int.Parse(tblcustomerdataview.Rows[rowno].Cells[0].Value.ToString());
custdatabean.Contactno = tblcustomerdataview.Rows[rowno].Cells[6].Value.ToString();
custdatabean.Emailid = tblcustomerdataview.Rows[rowno].Cells[7].Value.ToString();
custdatabean.Other = tblcustomerdataview.Rows[rowno].Cells[8].Value.ToString();
return custdatabean;
}
but in designer.cs I am getting an error in line:
this.toolStripMenuItem1.Click += new System.EventHandler(this.toolStripMenuItem1_Click);
The error is:
Error 1:
'WindowsFormsApplication3.CustomerDataBean WindowsFormsApplication3.CustomerSearch.toolStripMenuItem1_Click(object, System.EventArgs)' has the wrong return type D:\WindowsFormsApplication3\WindowsFormsApplication3\Merchandising\customerSearch.Designer.cs 83 46 NFTRANS
Where have I done something wrong?
Let me explain the situation
I had a jobcodeform where user should input the customercode in combobox if he forget customercode he can use a buton to go to another form called customersearch where there is a datagrid table with a context menustrip which when clicked gets the whole details of the selected row in a customerdatabean and return that back to the first jobcodeform
Your code doesn't make a lot of sense. Click events don't return anything (except void), they really just run a procedure.
Your quick fix is to match the signature of the handler:
private void toolStripMenuItem1_Click(object sender, EventArgs e)
{
// do something, don't return anything
}
What you need to define is what are you trying to do with your CustomerDataBean object. If you are just trying to add it to a list, then add it to a list:
private void toolStripMenuItem1_Click(object sender, EventArgs e)
{
CustomerDataBean custdatabean = new CustomerDataBean();
// set properties
myBeans.Add(custdatabean);
}
The code you currently have doesn't even create a CustomerDataBean object. It's null, and then you are trying to update a null object. That isn't going to work.
Ask yourself where should your click event return the object to?
What code will process that bean?
The others have explained what is wrong with your click event.
Here's one possible method:
Have your click event call a separate method to process the bean. Something like this, perhaps:
private void toolStripMenuItem1_Click(object sender, EventArgs e)
{
CustomerDataBean custdatabean = null;
int rowno = tblcustomerdataview.CurrentCellAddress.Y;
custdatabean.Customerpk = int.Parse(tblcustomerdataview.Rows[rowno].Cells[0].Value.ToString());
custdatabean.Contactno = tblcustomerdataview.Rows[rowno].Cells[6].Value.ToString();
custdatabean.Emailid = tblcustomerdataview.Rows[rowno].Cells[7].Value.ToString();
custdatabean.Other = tblcustomerdataview.Rows[rowno].Cells[8].Value.ToString();
processBean(custdatabean);
}
private void processBean(CustomerDataBean bean)
{
//Code to process the bean here.
}
ToolStripMenuItem click event handlers need to return void.

Categories

Resources