Xamarin IOS navigate to another view controller without button on xamarin - c#

i start using xamarin to create ios software.
in mainstoryboard, i navigate PageMain view controller to PageTo view controller.
I want navigate from PageMain view controller to PageTo view controller. i use this code and did not auto navigate:
var storyBoard = UIStoryboard.FromName ("MainStoryboard", null);
storyBoard.InstantiateViewController ("PageTo");
tried this one too but also not auto navigate :
PageMainViewController *viewController = segue. PageToViewController;
viewController.delegate = self;
tried this one too but also not auto navigate :
UIViewController pageto = new PageTo ();
pageto.Transition (PageMain, PageTo);
i know it, it easier use button to create push seque to PageTo view controller, but i did not want it.
please help me.

Another thing that you can do is push to another view controller...
AssignCaseController assignCaseController = this.Storyboard.InstantiateViewController("AssignCaseController") as AssignCaseController;
if (assignCaseController != null)
{
assignCaseController.CaseID = GetCurrentCaseID();
this.NavigationController.PushViewController(assignCaseController, true);
}

I hope this helps, I just had to do the same.
// Clear your notifications and other things
// Show the controller
// I am assuming your are using storyboards based in your use of Handle. I am also assuming the identifier in your storyboard for this is set to "WebViewController and its a custom subclass of UIViewController named WebViewController.
UIStoryboard Storyboard = UIStoryboard.FromName ("MainStoryboard", null); // Assume the name of your file is "MainStoryboard.storyboard"
var webController = Storyboard.InstantiateViewController("WebViewController") as WebViewController;
// ... set any data in webController, etc.
// Make it the root controller for example (the first line adds a paramater to it)
webController.CaseID = int.Parse(notification.UserInfo["ID"].ToString());
this.Window.RootViewController = webController;
// Note* the "Window" should already be set and created because the app is running. No need to remake it.

Related

Navigate between nested View Controllers across a TabBarController - Xamarin iOS

I'm having trouble with navigation outside of the typical use cases for navigation controllers and tabbar controllers. Here's a drawing of a simplified version. (real version has a TabBarController that feeds into 9 NavControllers)
In my Home Nav Controller, there's a table view where the user could select a row and that should navigate them to a particular Events Detail View Controller. At that point, the user should be able to navigate back to the Events TableView Controller to see the list of events or use the TabBar to navigate to another section.
So far with my code I can push the correct detail view controller and select the correct index of the tabbar but it only works the first time:
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
tableView.DeselectRow(indexPath, true);
var eventsDetailView = new EventsDetailController(eventPosts[indexPath.Row]);
//loop through ViewControllers array in case the user has set a custom tabbar order via the More Tab
foreach (UIViewController viewC in tbController.ViewControllers)
{
UINavigationController navController = viewC as UINavigationController;
if (navController.TabBarItem.Tag.Equals(9))
{
navController.PushViewController(eventsDetailView, false);
tbController.SelectedIndex = 9;
}
}
}
After the user has navigated to the events detail view controller, if they then:
travel to the Home ViewController via the TabBar
select a new TableRow to navigate to a different Events detail view controller
... then the same previous events detail view shows up. It doesn't matter which row the user selects in the Home View Controller. The initial detail view controller will always be the same one to be presented.
Any help pointing me in the right direction would be greatly appreciated!
Solution:
In my understanding, what you want is :
HomePageController --> EventDetailPage --> EvevtTableViewControll
So in the first step, you could push to EventDetailPage in HomePageController:
this.NavigationController.PushViewController(new HomeDetailUIViewController(), true);
Then, in your EventDetailPage, you can customize a back button, for example:
UIBarButtonItem backBtn = new UIBarButtonItem();
backBtn.Title = "back";
backBtn.Style = UIBarButtonItemStyle.Plain;
this.NavigationItem.LeftBarButtonItem = backBtn;
backBtn.Clicked += (sender, e) =>
{
// 1 here is an example, it should be the index of your EvevtTableViewControll
NavigationController.TabBarController.SelectedIndex = 1;
NavigationController.PopToRootViewController(true);
};
Set the NavigationController.TabBarController.SelectedIndex=1 first to make sure EvevtTableViewControll will show after you back from EvevtDetailViewControll, then your PopToRootViewController to back to the EvevtTableViewControll.
Try it and let me know if you have any problem.

UIPageViewController Xamarin

I need to implement a simple UIPageViewController using Xamarin in Visual Studio 2017 for mac.
As the documentation says in https://developer.xamarin.com/api/type/MonoTouch.UIKit.UIPageViewController/ I need to connect the previous and next views, using UIPageViewControllerDataSource.GetNextViewController and UIPageViewControllerDataSource.GetPreviousViewController from the UIPageViewControllerDataSource delegate, but I'm not clear where should I do that, nor I see any where to do that using the storyboard designer.
The idea to use the UIPageViewController is to add a quick tutorial of 4 pages before advancing to another View, at the last view of the UIPageViewController there would be a button that calls the segway to the next page.
You can add a UIPageViewController in the Storyboard. Configure the style in the Properties window => Widget(Navigation, Transition Style, Spine Location).
Then you can add the DataSource in the corresponding CS file. Add the firstly shown UIViewController using: SetViewControllers(new UIViewController[] { viewController }, UIPageViewControllerNavigationDirection.Forward, true, null);. Please notice that when you set the Spine Location to Mid, this array should contain at least two UIViewControllers. If not, add just one.
but I'm not clear where should I do that, nor I see any where to do
that using the storyboard designer.
When you want to navigate to the next page, the event GetNextViewController() will fire(i.e. first page - second page). And you should return which Controller will show in this event. Also GetPreviousViewController() means which Controller you want to show when navigate back. Here is my sample:
public class MyPageViewDataSource : UIPageViewControllerDataSource
{
List<UIViewController> pageList;
public MyPageViewDataSource(List<UIViewController> pages)
{
pageList = pages;
}
public override UIViewController GetNextViewController(UIPageViewController pageViewController, UIViewController referenceViewController)
{
var index = pageList.IndexOf(referenceViewController);
if (index < pageList.Count - 1)
{
return pageList[++index];
}
else
{
//when navigate to the last page, return null to disable navigate to next.
return null;
}
}
public override UIViewController GetPreviousViewController(UIPageViewController pageViewController, UIViewController referenceViewController)
{
var index = pageList.IndexOf(referenceViewController);
if (index == 0)
{
//when navigate to the first page, return null to disable navigate to previous.
return null;
}
else
{
return pageList[index - 1];
}
}
}
At last set your UIPageViewController's DataSource to this:DataSource = new MyPageViewDataSource(pageList);

NavigationController is null after setting RootViewController in Xamarin.iOS

I am using storyboards with Xamarin.iOS. The DashboardViewController (a UINavigationController) is set as the initial view in the storyboard. However, in my AppDelegate class, the FinishedLaunching method is conditionally checking if the user needs to login or not when the app starts up. If so, it will set the "ViewController" (login controller) as the RootViewController, or else it will instantiate the initial view controller as set by the storyboard, which is the "DashboardViewController". Here is the code for the FinishedLaunching method.
public override bool FinishedLaunching (UIApplication application, NSDictionary launchOptions)
{
// Override point for customization after application launch.
// If not required for your application you can safely delete this method
Window = new UIWindow(UIScreen.MainScreen.Bounds);
var storyboard = UIStoryboard.FromName("Main", NSBundle.MainBundle);
bool isLoggedOut = true;
UIViewController rootViewController;
if (isLoggedOut)
rootViewController = (UIViewController)storyboard.InstantiateViewController("ViewController");
else
rootViewController = (UIViewController)storyboard.InstantiateInitialViewController();
Window.RootViewController = rootViewController;
Window.MakeKeyAndVisible();
}
Once the user's credentials are verified, the following code attempts to set the RootViewController again back to the original "DashboardViewController" and present that view. This is done from the login controller.
partial void LoginBtn_TouchUpInside (UIButton sender)
{
var appDelegate = UIApplication.SharedApplication.Delegate as AppDelegate;
appDelegate.SetRootViewController (dashboardViewController, true);
this.PresentViewController (dashboardViewController, true, null);
}
Here is the code for the "SetRootViewController" in the AppDelegate:
public void SetRootViewController()
{
Window = new UIWindow(UIScreen.MainScreen.Bounds);
var storyboard = UIStoryboard.FromName("Main", NSBundle.MainBundle);
bool isLoggedOut = false;
UIViewController rootViewController;
if (isLoggedOut)
rootViewController = (UIViewController)storyboard.InstantiateViewController ("ViewController");
else
rootViewController = (UIViewController)storyboard.InstantiateViewController (viewController);
Window.RootViewController = rootViewController;
Window.MakeKeyAndVisible();
}
This works so far, but if I try to add another view to the stack in the DashboardViewController (which is a UINavigationController), saying from a button click using the following code,
partial void ProfileBtn_TouchUpInside (UIButton sender)
{
this.NavigationController.PushViewController (profileViewController, true);
}
the NavigationController is null and the app crashes. So the basic flow for this scenario is "Set RootViewController to "ViewController" so the user can log in --> When the user logs in set the RootViewController back to the DashboardViewController and present that view --> Click a button to navigate to another view from DashboardViewController view but the NavigationController in DashboardViewController is null.
What am I doing wrong?? Any help or advice would be appreciated (and I apologize for the long question).
I've decided to leave this question up for those that may come upon the same problem. I've figured out what I believe to be a solution. In my AppDelegate "SetRootViewController" method, instead of saying,
Window.RootViewController = rootViewController;
I needed to be saying,
Window.RootViewController = new UINavigationController(rootViewController);
with everything else staying the same. The workflow now works as expected. This is because the controller I am trying to set as the RootViewController is not just a UIViewController, it's a UIViewController wrapped by a UINavigationController. This answer is also reiterated here in the following link
https://forums.xamarin.com/discussion/23424/how-can-i-use-this-navigationcontroller-on-my-view
I apologize for answering my own question, if anybody has a better method or sees something wrong with this please let me know. Hope this helps someone in the future.

How do you load a url in a UIWebView

I just started creating a simple application in Xamarin C#.
I have two views : first view have a "login" button and a second view have a webView inside.
I have created the modal segue which connect those two views and my question is :
How can I get if second view is showing it's content and it's webView can load this url : "http://vk.com" ?
Well, at first, you need to add two views.
On the first view place a button. Connect this button to a second view(create a modal segue)
On the second view you can place a label or something different, it doesn't matter.
Zoom out your storyboard(in Xcode storyboard editor, "-" icon), select and set the second view class, for example, "view_two". Save and return to Xamarin Studio. Restart Xcode. Now, in Xamarin Studio select Your class file(in this case - view_two.cs) and open it. Then, insert this code in the "center" of the document :
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
this.webView_login.LoadRequest (new NSUrlRequest (new NSUrl ("http://vk.com")));
}
In the View's ViewDidLoad method:
string url = "http://vk.com";
webView.LoadRequest(new NSUrlRequest(new NSUrl(url)));
See also: http://docs.xamarin.com/recipes/ios/content_controls/web_view/load_a_web_page/
This below piece will will help.
UIWebView webView = new UIWebView(View.Bounds);
View.AddSubview(webView);
var documents = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
var yourWonFolderPath = Path.Combine(documents, "YourWonFolder");
var localDocUrl = Path.Combine(yourWonFolderPath, TicketInfo.TicketNumber + ".pdf");
webView.LoadRequest(new NSUrlRequest(new NSUrl(localDocUrl, false)));
webView.ScalesPageToFit = true;

InvalidOperationException raised when navigating back to a view

I've a child view (SharedView) that's shared between two parent views so I add it to each parent view through a Region like this
<StackPanel>
<ContentControl cal:RegionManager.RegionName="SharedViewRegion" />
</StackPanel>
In the parent view's ViewModel I register the child view like this
regionManager.RegisterViewWithRegion("SharedViewRegion", typeof(SharedView));
When I run the application if I open only one of the parent views it works as expected but if I open the two parent views then I get the following exception
An exception occurred while creating a region with name
'SecondRegion'. The exception was: System.InvalidOperationException:
Specified element is already the logical child of another element.
Disconnect it first.
I've been googling and this is the closer solution I found to my problem InvalidOperationException occurs when the same view instance is added to multiple ContentControl regions
But I'm using the prism navigation feature so I'm instancing the parent view like this
regionManager.RequestNavigate("ModuleRegion", new Uri("ParentView1", UriKind.Relative));
Can someone help me to solve this?
Try doing the following:
Add a name to the ContentControl that is hosting the region
Now you have to remove the region's content before leaving the parent view so in the ViewModel add the following code to the OnNavigatedFrom method
public void OnNavigatedFrom(NavigationContext navigationContext)
{
ParentView.MyContentControl.Content = null;
}
Note: You can access the parent view importing it in your ViewModel.
Now you need to add the content to the region by hand because you removed it before leaving the region. Here's the code
public void OnNavigatedTo(NavigationContext navigationContext)
{
SharedView view = (SharedView)ServiceLocator.Current.GetInstance(typeof(SharedView));
ParentView.MyContentControl.Content = view;
}
Note: In this method you must add some workaround because the first time you open this view you'll get a System.InvalidOperationException because PRISM will try to add the SharedView to MyContentControl.
Here's a possible workaround
bool isFirstTime = true;
public void OnNavigatedTo(NavigationContext navigationContext)
{
if (isFirstTime)
{
isFirstTime = false;
return;
}
SharedView view = (SharedView)ServiceLocator.Current.GetInstance(typeof(SharedView));
ParentView.MyContentControl.Content = view;
}
You have to do the same work in all parent views that share the SharedView
I hope this help you
You should directly add view to region instead of view discovery for this case. Give unique names to your parent views (you can use a counter to make up a unique name).
var region = this.regionManager.Regions["SharedViewRegion"];
var viewName = string.Format("SharedView{0}", this.countParent+1);
//Only add if it doesn't exist
var view = region.GetView(viewName);
if (null==view)
{
//Use container to get new instance of the parent view.
view = this.container.Resolve<SharedView>();
region.Add(view, name);
//Increment the counter as you added a new parent view
this.countParent++;
}
//Now activate the view
region.Activate(view);

Categories