A TabBarViewController cannot be presented as a child. Consider using Root instead - xamarin.ios

On the start of my iOS application (that I am building with Xamarin and MvvmCross), I want to immediately change UIViewController to a UITabBarViewController. My code:
public class MainViewModel : BaseViewModel
{
public void Initialization()
{
ShowViewModel<TabLayoutViewModel>(); // Breaks here
}
}
public class MainViewController : BaseViewController<MainViewModel>
{
public override void ViewDidLoad()
{
base.ViewDidLoad();
this.ViewModel.Initialization();
}
}
public class TabLayoutViewController : MvxTabBarViewController<TabLayoutViewModel>
{
}
On the line ShowViewModel<TabLayoutViewModel>() it throws an exception:
A TabBarViewController cannot be presented as a child. Consider using
Root instead
I just want to push this controller on top of the stack. I know this is legal in plain iOS so there should be a way to do it with MvvmCross?

Update: Since MvvmCross 5.0.4 it is now possible to show a TabBarController as a child. Just mark your TabBarController with [MvxChildPresentation].
See this PR to the source code..
Original answer:
A TabBarController is not meant to be presented inside a UINavigationController. What you can do is to change the root ViewController of your Window. To do so, you can add the MvxRootPresentation attribute above the TabLayoutViewController class.
If you do need to show tabs inside a UINavigationController, you might find this question relevant.

I had to do just that last week.
What I do to quickly resolve this is simple:
1) Create a custom presenter that inherits from MvxIosViewPresenter (https://github.com/MvvmCross/MvvmCross/blob/develop/MvvmCross/iOS/iOS/Views/Presenters/MvxIosViewPresenter.cs).
2) Override the ShowChildViewController method, using the original as model and comment these two lines:
if (viewController is IMvxTabBarViewController)
throw new MvxException("A TabBarViewController cannot be presented as a child. Consider using Root instead");
3) Override the CreatePresenter method in Setup.cs:
protected override IMvxIosViewPresenter CreatePresenter()
{
return new CustomTabChildMvxIosViewPresenter(ApplicationDelegate, Window);
}

Related

Xamarin.ios initialize UIView

I am using Xamarin.iOS. I have created UIView with a few UITextFields. I am looking for best way to initialize text value in these textfields from code.
I can pass text data in the constructor of UIViewContoller, but I don't have access to textFields inside it (they are null). I can change text value of textFields in viewDidLoad method.
I don't want to create additional fields in controller class to store data passed by constructor and use them in viewDidLoad. Do you know better solution ?
I don't want to create additional fields in controller class to store
data passed by constructor and use them in viewDidLoad.
But that's how it's meant to be done.
Alternatively, you can create less fields/properties in your viewcontroller if you use a MVVM pattern:
public class UserViewModel {
public string Name { get; set;}
public string Title { get; set;}
}
public class UserViewController : UIViewController
{
UserViewModel viewModel;
public UserViewController (UserViewModel viewModel) : base (...)
{
this.viewModel = viewModel;
}
public override void ViewDidLoad ()
{
userName.Text = viewModel.Name;
userTitle.Text = viewModel.Title;
}
}
That's the kind of pattern which gives you a lot of code reuse accross platforms (android, WP, ...) and clearly separate concerns. It's a (very) little bit of extra code, but it's worth every byte.

Not able to use Custom XIB outlets with UICollectionViewCell

When accessing to outlets from my CustomClass : UICollectionViewCell, they are appearing as not initialized and can not set a proper value.
Every example I've seen it uses a plain Class (no XIB) to set the UI.
[Register("CustomCommentCell")]
public partial class CustomCommentCell : UICollectionViewCell
{
public static readonly NSString Identifier = new NSString("CustomCommentCell");
public CustomCommentCell () : base()
{
}
public CustomCommentCell (IntPtr handle) : base (handle)
{
}
public void updateData()
{
this.lblComment.Text = "Test";
}
}
On the other hand, I have registered the Class:
this.tableComments.RegisterClassForCell (typeof(CustomCommentCell),commentCellId);
and have the GetCell properly set.
However, when trying to set the outlets to a specific value, it indicates it is null. (this.lblcomment = null) while it should have been a UILabel initialized.
Any clues?
to create the Custom CollectionViewCell using XIB. do the following
1) create C# class which inherits from UIcollectionViewCell
[Register("MyCustomCell")]
public class MyCustomCell : UICollectionViewCell
{
public static readonly NSString Key = new NSString ("MyCustomCell");
[Export ("initWithFrame:")]
public MyCustomCell(CoreGraphics.CGRect frame) : base (frame)
{
}
public override UIView ContentView {
get {
var arr= NSBundle.MainBundle.LoadNib ("MyCustomCell", this, null);
UIView view =arr.GetItem<UIView> (0);
view.Frame = base.ContentView.Frame;
base.ContentView.AddSubview (view);
return base.ContentView;
}
}
}
2) Add a IphoneView XIB file has the Same Name as that of Class created in step 1
3) Open XIB in XCODE and do the Following Changes
3.1)Select the FileOwner set the Class same name as Step 1
3.2)Select The View Set the Class name UIView
4) Design Your XIB Accordingly
I can't follow quite the problem you are seeing. What is a "Custom XIB outlet"? Why is this question tagged "custom-controls"? Is there some example code or pictures you can show to help explain the problem?
The approach I use for UICollectionViewCell's is the same as I use for UITableViewCell - see the tutorial - http://slodge.blogspot.co.uk/2013/01/uitableviewcell-using-xib-editor.html
Update: From the code you've posted as a comment (not sure if it's complete or not), I think it would be useful for you to follow through that tutorial. There are a few steps to complete including registering the custom class name and including using RegisterNibForCellReuse - one of those will probably fix this for you.

Need help with UITabBarController and orientation

I have an app (written using MonoTouch and currently working) that I want to add landscape orientation to. I am using a UITabBarController.
I don't see how to create a controller that will allow me to override the "ShouldAutorotate..." method. Can anybody point me to an example using a UITabBarController in MonoTouch?
TweetStation contains a sample precisely for this setup, and propagates the rotation down all of the nested view controllers.
Are you subclassing UITabBarController?
You are probably non subclassing and just adding a vanilla controller in Interface Builder. You have to subclass to override that property.
First make a new class like this:
//Test this, it's off the top of my head
[Register("YourTabController")]
public class YourTabController : UITabBarController
{
public YourTabController (IntPtr handle) : base (handle) { }
[Export("initWithCoder:")]
public YourTabController (NSCoder coder) : base (coder) { }
//Override should rotate
public bool ShouldAutoRotateToInterfaceOrientation(UIInterfaceOrientation o)
{ return true; }
}
Then, if you already have a UITabBarController in IB, there is a 'Class' property that you set to the name of your new class.

Compact Framework 3.5 Update Usercontrol With Main Form Variable Data

This seems like it should be simple, however, I cannot find an example through searching...
How do I update a label on a usercontrol using variables from its parent form?
I am building a compact framework 3.5 application.
Thanks for any and all assistance!!!
You can create a public property on the user control, and you update your label from there, for example:
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
public string LabelText
{
get
{
return label1.Text;
}
set
{
label1.Text = value;
}
}
}
You can also return the label itself, although some people may say that would break encapsulation on your design.

Accessing labels, textboxes and lauching views from TableViewDatSource

Just new to Monotouch! :D Very glad with it but still in the discovery phase... Hehehe...
I was wondering if i can see/change my labels from within my Table View, for example, in the Main.cs, please take a look:
public partial class AppDelegate : UIApplicationDelegate
{
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
//Do something in here (load my view or any other thing...)
}
public class TableViewDataSourceClientes : UITableViewSource
{
//Why can't I access my labels inside this class?
}
}
So, my question is pretty much it. Why i can access my labels and views and textboxes and etc. inside FinishedLauching and not in TableViewDataSourceClientes? ANd how can I achieve this?
My objective is to create a method inside of TableViewDataSourceClientes called RowSelected and change a label text when I select a row.
You cannot access your outlets/labels in the TableViewDataSourceClientes class because they are instance properties on your AppDelegate class. You can get at the AppDelegate from anywhere with UIApplication.SharedApplication.Delegate, you'll need to cast it to your AppDelegate type tho, and then expose the fields / properties you want as public members.

Resources