Xamarin.iOS data binding to a UICollectionViewCell and obtaining bound data within an event handler

JohnNolanJohnNolan USMember
edited May 2016 in Xamarin.iOS

I am having significant problems using Xamarin.iOS.

I come from a MVC5 web backgound and would often bind data to DOM elements (for example using data- attributes). I want to achieve a similar pattern in Xamarin.iOS.

From what I gather in Xamarin's documentation (which always seems to be based on obsolete versions of the framework) I need to bind data to a UICollectionViewCell using the KVC pattern I guess.

Is the best way of achieving this calling SetValueForKey(NSObject object, NString key) within my UpdateCell method. I have changed the code to be generic for the purpose of this post. UpdateCell() is called by my UICollectionViewSource within it's overridden GetCell() method - this code is omitted for brevity.

Here is my custom UICollectionViewCell class and its UpdateCell method :

 public class MyClassCollectionViewCell : UICollectionViewCell 
 {
     [Outlet]
     UILabel NameLabel { get; set; }

     public TimetableBaseCell (IntPtr handle) : base (handle)
     {
         this.NameLabel = new UILabel();
     }

     public virtual void UpdateCell(MyClass myClassObject)
     {
         // Display the "Name" within the UILabel outlet
         this.NameLabel.Text = myClassObject.Name;

         // This being my custom cell which inherits from UICollectionViewCell
         this.SetValueForKey(myClassObject, "MyClassObject");

         // remainder omitted for brevity
     }
 }

Here is MyClass.cs (again, not it's real name but for illustration):

// Should this not : NSObject? If so I cannot do this in my PCL library and would have to move models into the .iOS project...
public class MyClass 
{
     [JsonProperty("Id")]
     public int Id { get; set; }

     [JsonProperty("Name")]
     public string Name { get; set; }

     // more props omitted for brevity
}

The instance I am trying to bind does not inherit from NSObject and therefore will not work as argument 1 in the SetValueForKey method call I guess?

I am hoping to bind the object to a cell, tap the cell, retrieve data bound to cell and finally make a REST call using the bound data (my HTTP call needs to POST the myClassObject.Id value in the request body)

I want the "Name" property to appear on the UICollectionViewCell's label and the "Id" to be accessible for the REST call but not displayed to the user. Currently the label appears the TapGesture works but I am unable to retrieve the value for myClassObject.Id and thus cannot make a web call!

The UITapGestureRecognizer is wired up to the UICollectionView within my UICollectionViewController - code not required for scope of question) and correctly fires an event but requires the value for key "MyClassObject" or myClassObject.Id to POST as JSON...

Make sense?

All the best,

John

Best Answer

Answers

  • JohnNolanJohnNolan USMember

    I would also like to point I'm not bashing Xamarin - I think it's an awesome framework and now have probably the best tooling provider out there backing them. I can see though that it is still not a mature framework - I do hope more learning materials, SO presence and up to date literature is released soon...

  • JohnNolanJohnNolan USMember
    edited May 2016

    As @AdamKemp points out in the post here SetValueForKey is meant for NSObjects.

    So I refactored the code in MyClass.cs as follows

            [Register("MyClass)]
            public class My Class : NSObject
            {
                public MyClass() { }
    
                public MyClass(int ID)
                {
                    this.Id = ID;
                }
    
                private int _Id = 0;
                [Export("Id")]
                public int Id
                {
                    get
                    {
                        return _Id;
                    }
                    set
                    {
                        WillChangeValue("Id");
                        _Id = value;
                        DidChangeValue("Id");
                    }
                }
    
                // same for Name property
            }
    

    However when I call SetValueForKey within my UpdateCell method

        MyClass myClassObject = newMyClass(7); // int passed to constructor for illustration in my real code it's dynamic
    
        this.SetValueForKey(myClassObject, "MyClassObject");
    

    I encounter the following error

    Foundation.MonoTouchException: Objective-C exception thrown. Name: NSUnknownKeyException Reason: [<UICollectionViewCell 0x7e433a30> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key MyClassObject.

Sign In or Register to comment.