5

I want to be able to design my own UITableViewCell in IB. But I keep getting a null ref exception when trying to access the label I defined in IB.

Here's what I'm doing:

In Interface Builder:

  • I removed the "View" and added a UITableViewCell instead.
  • Changed the class of the UITableViewCell to "TestCellView".
  • Added a UILabel to the cell.
  • Added an outlet "oLblText" to TestCellView and connected the UILabel to it.
  • Changed the identifier of the class to "TestCellView".

Implement TestCellView.xib.cs

public partial class TestCellView : UITableViewCell
{
    public TestCellView(string sKey) : base(UITableViewCellStyle.Default, sKey)
    {
    }

    public TestCellView(IntPtr oHandle) : base(oHandle)
    {
    }

    public string TestText
    {
        get
        {
            return this.oLblText.Text;
        }
        set
        {
                        // HERE I get the null ref exception!
            this.oLblText.Text = value;
        }
    }
}

** The TestCellView.designer.cs**

[MonoTouch.Foundation.Register("TestCellView")]
public partial class TestCellView {

    private MonoTouch.UIKit.UILabel __mt_oLblText;

    #pragma warning disable 0169
    [MonoTouch.Foundation.Connect("oLblText")]
    private MonoTouch.UIKit.UILabel oLblText {
        get {
            this.__mt_oLblText = ((MonoTouch.UIKit.UILabel)(this.GetNativeField("oLblText")));
            return this.__mt_oLblText;
        }
        set {
            this.__mt_oLblText = value;
            this.SetNativeField("oLblText", value);
        }
    }
}

In my table's source:

public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
{
    TestCellView oCell = (TestCellView)tableView.DequeueReusableCell("myCell");
    if(oCell == null)
    {
        // I suppose this is wrong but how to do it correctly?
                // this == my UITableViewSource.
                NSBundle.MainBundle.LoadNib("TestCellView", this, null);
        oCell = new TestCellView("myCell");
    }
    oCell.TestText = "Cell " + indexPath.Row;
    return oCell;
}

Please note that I do NOT want a solution that involves a UIViewController for every cell. I have seen a couple of examples on the web doing this. I just think it is total overkill.

What am I doing wrong?

Stephane Delcroix
  • 16,134
  • 5
  • 57
  • 85
Krumelur
  • 32,180
  • 27
  • 124
  • 263

3 Answers3

3

You can not reference any outlets until the Nib is loaded. There is a method that you can override that will tell you "Your NIB is loaded, you can now access the fields". Until that point, referencing those objects will always return null.

miguel.de.icaza
  • 32,654
  • 6
  • 58
  • 76
3

First of all, it is a matter of design. If your table view always loads a specific number of cells with static content, like in a "Settings" view, create a custom cell for every row you want and connect each one with an outlet.

If this is not the case, then you have two options:

  1. Create a class that inherits the UITableViewCell and every view you want in it programmatically, forgetting Interface Builder.
  2. Add a new iPhone View with Controller, replace the view in there and treat it like you did. Except for the fact that you will have to connect your cell with an outlet in the File's Owner. So when you instantiate that controller, all your cell's subviews will be ok.

It is not an overkill, or at least, Apple recommends it: click and go to the "Loading Custom Table-View Cells From Nib Files" paragraph

PS: Just had a similar situation and this is the way I've done it. In MonoTouch, for this example, you do not have to LoadNib anything. Just do this inside the GetCell override in your table's source:

using (CellController controller = new CellController())
{

     cell = (CustomCell)controller.View;

}

Maybe even declare an extra outlet inside the CellController object to avoid casting from UIView.

Dimitris Tavlikos
  • 8,170
  • 1
  • 27
  • 31
  • 2
    That's exactly how I have it now. I just don't like having a controller. The reason is: when using the default cell styles I don't have a controller either. So THERE, Apple decided that NO controller is needed. When creaing custom cells, they want us to have one controller per cell. – Krumelur Mar 21 '11 at 09:11
  • 1
    Yes when you are using the default cell styles, no controller is needed since the cells are being created programmatically. But you want to use cells, user interface objects in general, that are loaded from a NIB file. Just dropping a custom cell in a NIB file isn't enough. It must be connected somehow with its File's Owner which, in this case, must be a UIViewController. – Dimitris Tavlikos Mar 22 '11 at 08:47
1

Check this link. This is a very interesting article for creating a custom TableViewCell. I think the error is due to the asynchronous loading of the xib provided by Monotouch.

You have to provide your own costructor like this:

public TestCellView(string sKey) //: base(UITableViewCellStyle.Default, sKey)
{
    MonoTouch.Foundation.NSBundle.MainBundle.LoadNib ("YOUR NIBNAME", this, null);
}

Hope this helps!

Lorenzo B
  • 33,216
  • 24
  • 116
  • 190
  • According to the link you provided here, the code example you entered above is not correct. The example in the link calls LoadNib inside the **controller** implementation and not inside the cell implementation. – Dimitris Tavlikos Mar 20 '11 at 19:13