How to add a custom view to a XIB file defined view in monotouch
Follow the following steps to use a custom view in a XIB:
First, decorate the view with the RegisterAttribute
:
[Register("MyView")]
public class MyView : UIView
{
}
and implement the following constructor:
public MyView(IntPtr handle) : base(handle) {}
This constructor is needed for when the runtime will try to recreate the view after it has been destroyed by a memory warning. After you have created your custom class:
- Open the XIB in Xcode (always by double-clicking on it through MonoDevelop) and add a
UIView
where you want it. - In Xcode, set that UIView's class to MyView (or whichever name you passed to the
RegisterAttribute
):
- Compile-Run.
EDIT:
Do not override LoadView
for controllers that are loaded from a XIB. LoadView
is meant to create the controller's view when that controller's view is not loaded from a XIB.
Creating a custom view using a xib
A very very nice question, but it is more about how XIBs work and what we can do about it.
The issue is when you add an object to a XIB and set it to be of a custom class, you just instruct the UIKit to create an instance of this object. The fact you see in IB as a view, a button or a whateverish control is just how IB draws it for you. This way the responsibility for creating the outlook falls completely on your class.
In Objective-C we can do a nice cheat to have XIBs with custom views and still add them to IB by setting the class name of the added view. This is possible because you can return any instance from the -init method of your class in Objective-C, which is not possible with C#.
However, you can still ease your life by doing the following:
- Let's define XIB to be a XIB which contains your custom view's content; Placement to be a XIB where you want to add you custom view.
- Create you custom view class and a XIB to lay the internals of it
- Handle AwakeFromNib method to actually load your XIB
- After having loaded your XIB just add the internals of it to your instance as subviews.
- Put a regular view and set it class to your own into Placement
- Enjoy!
You have, however, to accept that your XIB would contain a root view or something, which would be added as a subview onto the instance of your class put into Placement.
This way, you should have something like:
XIB with your custom view contents:
Placement where you add your XIB:
As the view instance added to your placement is the same as File Owner in your XIB you can set outlets and actions in both XIB and Placement. Just don't forget you root view in your XIB is not the instance UIKit will create to place into Placement.
For convenience purposes, please find my code below which is base class to ease the creation of such views:
using System;
using MonoTouch.ObjCRuntime;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
namespace Member.iOS.Base.Views {
/// <summary>
/// XibView is a Xib-backed UIView subclass which enables easy customization and custom
/// behavior addition.
/// </summary>
public class XibView : UIView {
/// <summary>
/// Exception thrown when a loaded XIB doesn't contain any views inside it.
/// </summary>
class EmptyXibException : Exception {
}
/// <summary>
/// Initializes a new instance of the <see cref="Member.iOS.Base.Views.XibView"/> class.
/// </summary>
/// <param name='handle'>
/// Handle.
/// </param>
public XibView(IntPtr handle) : base(handle) {
}
/// <summary>
/// Upon loading from a containing XIB, takes care of replacing the current instance (which acts as a stab) with
/// a real view loaded from its XIB.
/// </summary>
public override void AwakeFromNib() {
base.AwakeFromNib();
NSArray views = NSBundle.MainBundle.LoadNib(GetType().Name, this, new NSDictionary());
if (views.Count == 0) {
throw new EmptyXibException();
}
UIView rootView = Runtime.GetNSObject(views.ValueAt(0)) as UIView;
rootView.Frame = new System.Drawing.RectangleF(0, 0, Frame.Width, Frame.Height);
AddSubview(rootView);
}
}
}
How to create a UIView with Xib in MonoTouch
You have to decorate your UITableViewCell class with the RegisterAttribute before opening the XIB in Xcode.
Check this answer.
Monotouch custom UIView
I found a solution that works.
m_ActivityView = Activator.CreateInstance<ActivityUtilityView>();
var view = NSBundle.MainBundle.LoadNib("ActivityUtilityView",m_ActivityView,null);
m_ProgressView = Runtime.GetNSObject(views.ValueAt(0) as ActivityUtilityView;
Creating the view using the IntPtr constructor does not instantiate the IBOutlets until the view has been displayed. This method appears to.
To clarify the issue arrose due to a race condition on background worker threads.
How do you add a custom UIViewController to existing XIB?
For a normal UIView, the basic steps you need to go through are:
Create your custom view in C# as a class
public class MyView
{
}Add the UIView base class to it, add a Register attribute and add two constructors:
[Register("MyView")]
public class MyView : UIView
{
public MyView() {}
public MyView(IntPtr handle) : base(handle) {}
}To make it do something useful, then add a Draw implementation:
public override Draw(RectangleF rect)
{
var context = UIGraphics.CurrentGraphics();
UIColor.Red.SetFill();
context.FillEclipseInRect(rect);
}Save and Build your project
Now in the XIB editor for the UIViewController in which you want to use your custom view, add a UIView to the design surface
Select that UIView and in the Identity Inspector, set the UIView's "Custom Class" to "MyView"
Save everything in xCode
Return to MonoDevelop, build and run
There's a video of this flow available at:
- http://www.youtube.com/watch?v=ggwO46dd-50&feature=youtube_gdata
For a custom UICollectionView, UILabel, UITableViewCell, or any other UIView base class, then you follow similar steps, just with a different base class and with different constructors too in order to support the specific View.
For a video about custom Table cells, see: http://slodge.blogspot.co.uk/2013/01/uitableviewcell-using-xib-editor.html
Related Topics
Style Bundling Not Working After Iis Deployment (MVC 4)
What Is a Dynamic Language, and Why Doesn't C# Qualify
C# Version of Java's Synchronized Keyword
What Setup Code Should Go in Form Constructors Versus Form Load Event
What Is the Connection String for Localdb for Version 11
Best Way to Determine If Two Path Reference to Same File in C#
Convert Arabic"Unicode" Content HTML or Xml to PDF Using Itextsharp
Classes Residing in App_Code Is Not Accessible
Difference Between Await and Continuewith
ASP.NET - Problems with Static Selected Style for a Selected Page on the Menu
In Ruby, What Is the Equivalent to an Interface in C#
Why New Fb API 2.4 Returns Null Email on MVC 5 with Identity and Oauth 2
Serialization of Entity Framework Objects with One to Many Relationship
Writing Recursive Cte Using Entity Framework Fluent Syntax or Inline Syntax