views:

31

answers:

2

I'm using Silverlight 4 on IE 8. I have created a new Silverlight web part for SharePoint 2010 that I am using to read 2 external content types. One represents the Invoices in the Chinook database from Code Plex and the other is the lines of each invoice. I am attempting to display the code in a Master-Detail layout using the Telerik Rad GridView control. I have tried this code in several different ways. Here is a general discription: I have 2 objects InvoiceHeader and InvoiceLine.

Invoice header contains a list of InvoiceLines

public List<InvoiceLine> lines { get; set; }

The only way I was able to get this to "work" was to use a foreach and cycle through the returnedInvoices and then use a sub foreach(var invoice in returnedInvoices) and add each line to a list and then adding the list to the current invoice using invoice.lines.Add(new InvoiceLine(line));

Of course the problem was that I could not clear lines using lines.Clear() or all of the lines were cleared in all of the InvoiceHeader objects. Since I could not clear the list each invoice had the follwing invoices lines added to its own lines. So I created a tracking array of InvoiceHeaders and tried using it to do tracking[x].lines.Add(new InvoiceLine(line)); and I then received the error in my subject for this post. Object reference not set to an instance of an object when trying to add an InvoiceLine to the InvoiceHeader object's List. I'm not really a developer, so I would appriciate any help you can give me. Currently the code has become crazy, so my appolgies for that. I have included the succeededCallback below:

 void succeededCallback(object sender, ClientRequestSucceededEventArgs e)
        {

                this.Dispatcher.BeginInvoke(() =>
                    {

                        invoices.Clear();
                        invoiceLines.Clear();
                        int x = 0;
                        int y = 0;
                        foreach (var inv in returnedInvoices)
                        {
                            x++;
                        }

                        InvoiceHeader[] tracker = new InvoiceHeader[x];

                        foreach (var invoice in returnedInvoices)
                        {
                            tracker[y] = new InvoiceHeader(invoice);

                             //Get the lines that correspond to this invoice.
                            foreach (var line in returnedLines)
                            {
                                if(line.FieldValues["InvoiceId"].ToString() == invoice.FieldValues["InvoiceId"].ToString())
                                { 
                                    //tracker[y].lines.Add(new InvoiceLine(line));
                                    /*
                                     * If I comment out the line above
                                     * I do not get the error, but I also
                                     * don't get my detail level.
                                     */
                                }

                            }

                            invoices.Add(tracker[y]);
                            if (y < x) { y++; }
                        }

                        radGridView1234.ItemsSource = invoices;                        
                    }
                    );

        }
+1  A: 

When are you initializing lines? Typically, collection properties only have a getter with a private setter when used as an autoproperty.

public List<InvoiceLine> lines { get; private set; }

You must initialize it as you're currently calling .Add on a null.

lines = new List<InvoiceLIne>();
Marc
Marc and annakata, Thak you both! Of course that was it! Pretty noobish mistake on my part.
Robert Kaucher
A: 

I can't see a reference to lines in your code sample which I couldn't really follow, but this exception means you have a null reference. Auto properties like your lines declaration have an initial value of the default for the type, which for a List means null, hence boom.

It's not recommended to expose Lists directly through a property because the behaviour you'll get rarely matches what you intended, and I would suggest you refactor that to a non-autoprop encapsulating a private and initialised field, i.e.:

// private field for your data
private List<InvoiceLine> _lines = new List<InvoiceLine>();

// public prop to expose it - but I'd be better still if I just exposed an Add method.
public List<InvoiceLine> Lines
{
  get { return this._lines; }
}

But for this problem right now, the simplest thing to do is just to set lines = new List<InvoiceLine>(); at some point before you try and add to it - in the constructor from preference.

annakata