Programmatically changing tabs in a Monotouch app - xamarin.ios

Forgive me for my ignorance, as I'm new to Monotouch and I'm sure this is a simple thing but I can't find the answer anywhere.
I have an iPhone app in Monotouch that uses a UITabBarController for root navigation. It is defined in it's own class file. There is also a separate view controller class file for the content of each tab. So tab1 shows viewcontroller1, tab2 shows viewcontroller2, etc.
I want a user to be able to click on button1 inside of viewcontroller1 and have the app take them to tab2 and show viewcontroller2.
I have an event handled for the click of button1 and I can do things like pop up alerts when it's clicked, but I can't figure out how to get the tab bar to be accessible for me to call it. Please help!
Edit: I need to know not only how to make it accessible, but I also don't know what method to call to make it change.

When you create your "child" view controllers, pass in a reference to the "parent" tab controller. Then you child can call a method on it's parent to update the current tab index.

something like
btn1.TouchUpInside += (sender, args) => TabBarController.SelectedIndex = 0 ;

Related

Create a generic popup panel

I have added a Global Button with the following code.
public override void Initialize()
{
if (!String.IsNullOrEmpty(Base.PrimaryView))
{
Type primaryViewItemType = Base.Views[Base.PrimaryView].Cache.GetItemType();
PXAction action = PXNamedAction.AddAction(Base, primaryViewItemType, "SubmitTicket", "Submit Ticket", TestClick);
}
}
public IEnumerable TestClick(PXAdapter adapter)
{
throw new PXException("Button clicked from graph" + Base.GetType().Name);
}
And it renders the button like this in each of the pages.
Now, I would like to display a popup panel, on button's click. I know I can create a popup panel on screen section. But, is there some way that I can have a general popup panel created in one place and can be displayed on each of the pages on the button's click?
Thank you.
As #HB_ACUMATICA mentioned there is no good easy way.
Providing another alternative to his post, you can create a graph and use it as a reusable popup by calling:
throw new PXPopupRedirectException(graph, string.Empty, true)
One thing I ran into was a sizing issue on the popup...
Changing the height/width when calling another graph as an in-page popup using PXPopupRedirectException
If you do copy and paste the PXSmartPanel you can create re-usable business logic by implementing the reusable business logic pattern found in this help as a starting point:
Reusing Business Logic
If I understand correctly you want to share the same PXSmartPanel control in different pages without having to copy/paste it in every screen.
In Acumatica Framework this is achieve by custom container controls like 'PXUploadDialog' which derives functionality from other controls like 'PXSmartPanel'. This is the control that is used when you attach files in all screen.
Unfortunately there seems to be no documentation on how to achieve this.
The closest I found is this SO question which is essentially unanswered:
Create custom User Control for Acumatica
Considering this, you may want to copy/paste the same smart panel in all screen.
To ease copying you can use the 'Edit ASPX' feature, make sure you backup the project before.
Edit ASPX to get to the code:
Copy paste your smart panel in the page and click 'GENERATE CUSTOMIZATION SCRIPT' to package the changes in the project:

How do you use a storyboard reference in a Tab Bar Controller with Visual Studio?

I have a view controller in one storyboard that I'd like to reuse in another storyboard's Tab Bar Controller. In XCode, I can add a storyboard reference and then ctrl-drag from the Tab Bar Controller to it, and it shows up as another tab, just like a View Controller would in the same storyboard. I'm trying to do this in VS 2017 though and it doesn't seem to work. Or if it does, I'm unsure of how to do it. I tried adding a storyboard reference and ctrl-dragging, just like I do for normal View Controllers. I select "Tab" under "View Relationship" which pops up when I finish dragging, but it never makes the link and never makes the tab.
Is this even something that is valid? And if it is, is it a bug/limitation with VS that I can't do this, and is there a workaround?
Edit:
I managed to get this to work programmatically. Here's what I did in case anyone wants to know. However, I still would like to know the answer to my previous questions.
First, in your desired VC (I'm going to call it TestVC), make sure you add a Tab Bar Item (not a tab bar). Set up the title and image as you would normally. Then, in your Tab Bar Controller's ViewDidLoad method, do something like this:
var storyboard = UIStoryboard.FromName("StoryboardNameTestVCIsIn", null);
var vc = storyboard.InstantiateViewController("TestVC");
var existing = new List<UIViewController>(ViewControllers);
existing.Add(vc);
ViewControllers = existing.ToArray();
Is this even something that is valid? And if it is, is it a bug/limitation with VS that I can't do this, and is there a workaround?
It is not support to add Tab relationship by this way. As you mentioned above, you could only implement that programmatically. Maybe in the near future Xamarin will support it like in Xcode.
Click on the segue , and you can see all the actions you can do.

Proper way to change a instantiate button in parent view/control

I'm creating a single-page web app that has one controller for the overall page (PageController) and separate child controllers for two views (ViewController and EditController).
ViewController needs a button called "Edit" in the titlebar of the app, EditController needs a button called "Save". The buttons occupy the same space, but have different labels and different on-click handlers. The titlebar belongs to the parent template/controller (i.e. PageController) scope.
One way to accomplish this is to create the button in the parent scope and let the child controllers change the text and override the ng-click handler - but I'm thinking there's probably a better way with Angular. I'd like some way for the child controllers to "inject" (not sure if this is the proper use of the word here) their button into to the parent template and handle the onclick locally, making the parent agnostic of what goes on in the child controllers...
I would think about your "views" differently. To me, titlebar is a view, just like your View and Edit views. It should therefore either contain all of the HTML it needs to render whatever you might want to show in that view, or it should know which files to ng-include.
Views are driven by models. The View and Edit controllers should call methods defined on whatever controller (or service) contains the titlebar model to set some state/properties appropriately. The titlebar view/HTML would use ng-show/hide or ng-include directives to show/include the appropriate HTML based on the current state of the model/$scope.
To be notified of a button click, the View and Edit scopes could $watch a model/$scope property for a change. E.g., <a ng-click="buttonState.clicked=true">...</a> I'm using an object with a clicked property so that the child controllers can reset the value inside their $watch callbacks (if a primitive was used, resetting would not work -- a new child scope property would be created):
$scope.$watch('buttonState.clicked', function() {
buttonState.clicked = false
... handle button click here ...
}

Monotouch use UITabBarController inside DialogViewController

Currently in my app I have this design:
-- DialogViewController 1
-----DialogViewController 2
--------DialogViewController 3
-----------TabBarController
--------------DialogViewController4
--------------DialogViewController5
--------------DialogViewController6
--------------DialogViewController7
Problem with this is that dialog view controllers 4-7 breaks the monotouch dialog flow (so to speak), because of TabBarController in between. When I create dialog view controllers 4-7 I need to create new Root in their constructors which I don't need to for DVC 1-3.
With this approach certain things like radio groups don't work inside DVC 4-7 e.g it will display the radio group selection, but there is no navigation bar at the top.
My question is what can I do to solve this? Can I use TabBarController inside DVC somehow if that makes sense? Or how can I "hook" DVC 4-7 back to main "circuit"?
Thanks in advance.
According to the iOS HIG
A tab bar appears at the bottom edge of the screen and should be
accessible from every location in the app
which implies that it should be the root, not nested inside another controller.

How does MonoTouch autogenerate XIB code behind?

I'm a C# programmer dabbling in a bit of iPhone development using MonoTouch.
I add a new View Interface Definition to my project and double click to open it up in Interface Builder. I add a UIButton. I save the file, and inspect the xib.designer.cs file, and I can see no reference to the new button.
I downloaded the code from http://monotouchexamples.com/ where I could see an example of autogenerated code behind :
[MonoTouch.Foundation.Connect("infoButton")]
private MonoTouch.UIKit.UIButton infoButton {
get {
return ((MonoTouch.UIKit.UIButton)(this.GetNativeField("infoButton")));
}
set {
this.SetNativeField("infoButton", value);
}
}
I opened up MainWindow.xib in interface builder. I notice a few differences. File's Owner is of type UIApplication instead of NSObject. What is the importance of this? There is an App Delegate object of type AppDelegate. I can't add an AppDelegate to my own view, or at least I can't find it in the Library. Do I need to add one? I can see that the existing controls on MainWindow.xib have Referencing Outlets to the App Delegate. I add a new button and I want to hook it up. When I click and drag a New Referencing Outlet to the App Delegate a context menu appears that lists the existing controls. How do I add a new element to this list, or where does this list come from?
I've been spoilt by the Visual Studio world where I just dump a button on a form and start writing code for the click event. Could someone provide some pointers about the steps needed to get this working on MonoTouch?
Thanks,
Patrick
Adding a button by itself is not enough. The button is not accessible outside the Interface Builder. You need add an Outlet, and connect the button with the outlet in Interface Builder.
Remember: Outlets are the members in your Controller class that get a reference to the controls, you can't just access the controls without them.
As Dave says, you need to add an outlet to your controller class, and connect your button to that outlet, before any auto-generated code will appear. This caught me out too initially.
You choose your controller class in the Interface Builder library window, choose 'outlets' in the bottom part of the library, and add an outlet there. You then need to select your button, choose the connections tab of the inspector window, and drag from the "New referencing outlet" circle over to your controller class. Interface Builder will then prompt you to choose an outlet to connect to. Then when you save, you should get the auto-generated code appear in the .xib.designer.cs file, and then you should be able to reference your button via that outlet variable in your .xib.cs file.
It sounds like the project I created is out of date - I remember there were quite a few changes around how the generated buttons are created in the designer file. I will update the project soon for you.
As Dave said, to get the code to be auto generated you need to add an outlet with Interface Builder. There should be an example on this video here - http://bit.ly/aWoItN but the server seems to be down at the moment.
Hope this helps,
ChrisNTR

Resources