I have a scenario where I want to call a method when the user of the app navigates to a certain tab of the TabbedPage.
Example: If I navigate to tab no. 3 of my TabbedPage, a certain method shall be called.
How do I achieve that?
By default all tabs of the TabbedPage are loaded when I start the app.
I am writing in Xamarin - C#.
Best regards!
There are two sample ways to achieve that.
One is using OnAppearing method inside the needed item of tab page.
For example, the tab no. 3 of TabbedPage is ItemsPage, then its ItemsPage.xaml.cs code as follows:
public partial class ItemsPage : ContentPage
{
public ItemsPage()
{
InitializeComponent();
}
protected override void OnAppearing()
{
base.OnAppearing();
// Call your needed method here
}
}
The another way is using OnCurrentPageChanged methond inside the tabbedpage.xaml.cs.
For example, the code as follows:
public partial class MainPage : TabbedPage
{
public MainPage()
{
InitializeComponent();
}
protected override void OnCurrentPageChanged()
{
base.OnCurrentPageChanged();
if(CurrentPage.Title == "tab no. 3 title")
{
// call your needed method
}
//Console.WriteLine(CurrentPage.Title);
}
}
Related
I'm currently working on the POM of a web app, that allows to open modals from the navigation bar. The navigation bar stays the same for every page you're on. Each modal can be opened from every page.
I have defined a page object for each modal. Also the navigation bar is a pageobject,
What would be the best way to return to the page, that the modal was opened from?
So for example, you are on the Page FooPage and open modal AboutModal. What is the best way to return to FooPage? It should also work for BarPage and other Pages.
My first approach was, that i define a BasePage Object, which only includes the webdriver and navigationbar. i extend every Page on the web app from this BasePage. Then i could do something like this:
Code for FooPage:
public class FooPage: BasePage
{
private NavigationBar NavBar;
public FooPage(IWebDriver driver): base(driver)
{
...
this.NavBar = new NavigationBar(driver);
}
public NavigationBar Navigate()
{
return NavBar;
}
...
}
public class NavigationBar
{
...
public openAboutModal(BasePage currentPage)
{
log.Info("Open About Modal");
Action.Click(NavigationBarElements.AboutButton);
return new AboutModal(Driver, currentPage);
}
}
public class AboutModal
{
...
protected BasePage ReturnPage;
public AboutModal(IWebDriver driver, BasePage returnPage)
{
...
this.ReturnPage = returnPage;
}
public BasePage CloseAboutModal()
{
return this.ReturnPage;
}
...
}
This is not practical and not intuitive, because we have to remember on which pageobject we currently are, when writing tests. Also only the methods from BasePage are available, which means we have to additionaly navigate back to the page we wanted to be on.
So instead of writing
public class ModalTests
{
[Test]
public void CheckAboutModal()
{
Login() // FooPage
.Navigate() //NavigationBar
.openAboutModal() // AboutModal
.doSomeStuff() //AboutModal
.CloseAboutModal(); //FooPage
}
}
we have to do
public void CheckAboutModal()
{
Login() // FooPage
.Navigate() //NavigationBar
.openAboutModal(new FooPage(Driver)) // AboutModal
.doSomeStuff() // AboutModal
.CloseAboutModal() // BasePage
.Navigate() //NavigationBar
.ToFooPage(); // FooPage
}
}
How can I return to the calling Page of the modal, without making Testwriting to complicated?
Rather than write your test as one giant method-chaining call, use variables whenever you need to refer back to a certain page model. Your test can simply become:
var foo = Login();
foo.Navigate()
.openAboutModal()
.doSomeStuff()
.CloseAboutModal();
// Continue your test after closing the modal
foo.SomeOtherOperation();
In cases like this, the modal doesn't need to return anything. The CloseAboutModal() method can be a void return type. Your test should understand the larger context in which the modal is being used, and create local variables appropriately in order to "return" back to the main page.
I am trying to make an app with a Main Page that is a plain Content Page (i.e. no toolbar) which has a button that leads into a Navigation Page (with toolbar). I'm struggling to find any resources to help me out in this specific case.
I have tried the following. In my App.xaml:
public partial class App : Application
{
public App ()
{
InitializeComponent();
MainPage = new App5.MainPage();
Pallets = new NavigationPage(new Pallets()); //Error: 'Pallets' is a type but is used like a variable
}
...
}
Above is the error I get on Pallets. I could change Pallets for MainPage and write the whole app with Navigation pages, which I will do for now, but I would prefer not to.
In my MainPage.xaml.cs, I'm trying to switch the view when the button is clicked:
public partial class MainPage : ContentPage
{
...
async void Button_Clicked(object sender, EventArgs e)
{
await Navigation.PushAsync(new Pallets());
}
}
I have seen examples such as this that include Navigation Page to Navigation Page buttons, but not plain Content Page to Navigation Page buttons.
I am trying to build a Xamarin Forms Mobile Application using Prism (Unity) Framework - and add a iOS keyboard extension to the Mobile App.
I added the Keyboard Extension Project and added the reference to the iOS application.
I added a ViewController in the Keyboard Extension Project (which created an XIB file as well) as below:
public partial class ViewController1 : UIViewController
{
public ViewController1() : base("ViewController1", null)
{
}
public override void DidReceiveMemoryWarning()
{
base.DidReceiveMemoryWarning();
// Release any cached data, images, etc that aren't in use.
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
// Perform any additional setup after loading the view, typically from a nib.
}
}
When I rebuild and run, and install the keyboard and click on the keyboard icon to switch, the view of the keyboard is not returned.
Here is the code for the App.xaml.cs in main application
public partial class App : PrismApplication
{
public App(IPlatformInitializer initializer = null) : base(initializer)
{
}
protected override void OnInitialized()
{
InitializeComponent();
NavigationService.NavigateAsync("NavigationPage/MainPage?title=Hello%20from%20Xamarin.Forms");
}
protected override void RegisterTypes()
{
Container.RegisterTypeForNavigation<NavigationPage>();
Container.RegisterTypeForNavigation<MainPage>();
}
}
I don't know what's missing...?
I can't find any answers on how to bind the view of the Keyboard by code because I am building this using a Windows PC .. any help would be appreciated.
You have to create an instance of your keyboard view and assign that object to your view controller View property:
public override void ViewDidLoad()
{
base.ViewDidLoad();
//bind view to controller
var viewNib = UINib.FromName("KeyboardView", null);
View = viewNib.Instantiate(this, null)[0] as UIView;
}
Replace "KeyboardView" with name of your .xib file
I'm currently reading the navigation section from An Introduction to Xamarin.Forms. One should use the GetMainPage() method. But how should that be used?
The default implementation of the app delegate looks like the following:
Applicaton Delegate:
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
global::Xamarin.Forms.Forms.Init ();
LoadApplication (new App ());
return base.FinishedLaunching (app, options);
}
}
App:
public class App : Application
{
public App ()
{
MainPage = GetMainPage ();
}
public static Page GetMainPage()
{
var mainNav = new NavigationPage(new ListExample());
return mainNav;
}
}
I got it managed to use the GetMainPage()method instead of getting
Application windows are expected to have a root view controller at the end of application launch
If I look into the (old?) examples (example1, example2) the app delegate is different and a CreateViewController() method is available. In my case it is not!
What is the correct way of loading the root page on to the stack?
You don't have to use GetMainPage(); that's just a method you create. The way X.Forms works these days is: it exposes a MainPage property in the Xamarin.Forms Application class. You set this to an instance of a Page. How you create that page is up to you. You can either use
this.MainPage = new ContentPage { Content = ... }
or you create one file per page (which IMHO is best for maintainability):
this.MainPage = new MyLoginPage();
or you use helper methods which create your pages:
this.MainPage = this.GetMainPage();
The main page is the first page of your Forms application. You can set the MainPage property to a different value to show another page.
Earlier versions of Forms used different approaches and not all samples have been updated yet. Now all platforms only need a call to the Forms Init() method and a call to LoadApplication() instead of creating a view controller, an activity or a page (WP8).
we have a rather large Silverlight application and we need to add some extra functionality to it.
The App consists of an Frame-Element and a TreeView w/ HyperlinkButtons for the navigation. Every content which will be loaded into the main Frame is a Page.
Now, I need to hook into every Page's unload event. Currently we use something like this:
/* PageX.xaml */
<navigation:Page
x:Class="Foo.Views.PageX"
<!-- namespacing -->
Title="Test Page X"
Unloaded="Page_Unloaded">
...
</navigation:Page>
Code-behind:
/* PageX.xaml.cs */
/* usings */
namespace Foo.Views
{
public partial class PageX : Page
{
public PageX() {
InitializeComponent();
}
private void Page_Unloaded(object sender, RoutedEventArgs e) {
/* CODE */
}
}
}
This approach need to be implemented on each and every Page, as the code within the unloaded method stays exactly the same... As I mentioned earlier, we have a couple of Pages and it would be much more useful to create a custom Page-class where this Page_Unloaded() is implemented directly, so that we don't need to alter every Page.
Can you please tell me how to create such a custom Page-class?
Thanks in advance for any help!!
Kind regards!
You could create a base Page class that all your pages inherit from which registers the event in the constructor...
public class BasePage : Page
{
public BasePage()
{
Unloaded += Page_Unloaded;
}
void Page_Unloaded(object sender, RoutedEventArgs e)
{
}
}
Then all your pages could inherit from that...
public partial class Page1 : BasePage
{
public Page1()
{
InitializeComponent();
}
}
...and in the xaml of each page...
<base:BasePage x:Class="WPFApp.Page1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:base="clr-namespace:WPFApp">
<Grid>
</Grid>
</base:BasePage>