it-swarm.com.de

Wie wechseln Sie Seiten in Xamarin Forms?

Wie wechseln Sie zwischen Seiten in Xamarin-Formularen? Meine Hauptseite ist eine ContentPage und ich möchte nicht zu so etwas wie einer Registerseite wechseln.

Ich konnte es pseudo machen, indem ich die Eltern der Steuerelemente fand, die die neue Seite auslösen sollen, bis ich die ContentPage gefunden habe, und dann den Inhalt mit den Steuerelementen für eine neue Seite austauschen. Aber das scheint wirklich schlampig zu sein.

Vielen Dank

79
Eric

Xamarin.Forms unterstützt mehrere integrierte Navigationshosts:

  • NavigationPage, wo sich die nächste Seite befindet,
  • TabbedPage, die Sie nicht mögen
  • CarouselPage, um links und rechts zur nächsten/vorherigen Seite zu wechseln.

Darüber hinaus unterstützen alle Seiten auch PushModalAsync(), die einfach eine neue Seite über die vorhandene Seite schieben.

Wenn Sie am Ende sicherstellen möchten, dass der Benutzer nicht mit einer Geste oder der rückwärtigen Hardwaretaste zur vorherigen Seite zurückkehren kann, können Sie die gleiche Page angezeigt lassen und deren Content ersetzen.

Die vorgeschlagenen Optionen zum Ersetzen der Stammseite funktionieren ebenfalls, aber Sie müssen für jede Plattform anders damit umgehen.

57

In der App-Klasse können Sie die MainPage auf eine Navigationsseite und die Stammseite auf Ihre ContentPage setzen:

public App ()
{
    // The root page of your application
    MainPage = new NavigationPage( new FirstContentPage() );
}

Dann in Ihrem ersten ContentPage-Aufruf:

Navigation.PushAsync (new SecondContentPage ());
49
David Douglas

Wenn Ihr Projekt als PCL-Formularprojekt eingerichtet wurde (wahrscheinlich auch als Shared Forms, aber ich habe es nicht versucht), gibt es eine Klasse App.cs, die folgendermaßen aussieht:

public class App
{
    public static Page GetMainPage ()
    {     
        AuditorDB.Model.Extensions.AutoTimestamp = true;
        return new NavigationPage (new LoginPage ());
    }
}

sie können die GetMainPage-Methode ändern, um ein neues TabbedPaged oder eine andere Seite zurückzugeben, die Sie im Projekt definiert haben

Von dort aus können Sie Befehle oder Event-Handler hinzufügen, um Code auszuführen und auszuführen 

// to show OtherPage and be able to go back
Navigation.PushAsync(new OtherPage());

// to show AnotherPage and not have a Back button
Navigation.PushModalAsync(new AnotherPage()); 

// to go back one step on the navigation stack
Navigation.PopAsync();
34
Sten Petrov

Schieben Sie eine neue Seite auf den Stapel und entfernen Sie die aktuelle Seite. Dies führt zu einem Wechsel. 

item.Tapped += async (sender, e) => {
    await Navigation.PushAsync (new SecondPage ());
    Navigation.RemovePage(this);
};

Sie müssen sich zuerst auf einer Navigationsseite befinden:

MainPage = NavigationPage(new FirstPage());

Das Wechseln von Inhalten ist nicht ideal, da Sie nur eine große Seite und einen Satz von Seitenereignissen wie OnAppearing ect haben. 

22
Daniel Roberts

Wenn Sie nicht zur vorherigen Seite wechseln möchten, d. H. Den Benutzer nach der Autorisierung nicht zum Anmeldebildschirm zurückkehren möchten, können Sie Folgendes verwenden:

 App.Current.MainPage = new HomePage();

Wenn Sie die Rückfunktionalität aktivieren möchten, verwenden Sie einfach 

Navigation.PushModalAsync(new HomePage())
3
Baqer Naqvi

Mit der PushAsync () - Methode können Sie Push und PopModalAsync () verwenden, um Seiten zum und vom Navigationsstapel zu platzieren. In meinem folgenden Codebeispiel habe ich eine Navigationsseite (Stammseite), und von dieser Seite aus drücke ich eine Inhaltsseite, die eine Anmeldeseite ist, sobald ich mit meiner Anmeldeseite fertig bin. Ich kehre zur Stammseite zurück

~~~ Navigation kann als Last-In-First-Out-Stack von Page-Objekten betrachtet werden. Um von einer Seite zu einer anderen Seite zu gelangen, schiebt eine Anwendung eine neue Seite auf diesen Stack. Um zur vorherigen Seite zurückzukehren, springt die Anwendung die aktuelle Seite aus dem Stapel. Diese Navigation in Xamarin.Forms wird von der INavigation-Schnittstelle verwaltet

Xamarin.Forms verfügt über eine NavigationPage-Klasse, die diese Schnittstelle implementiert und den Stapel von Pages verwaltet. Die NavigationPage-Klasse fügt außerdem am oberen Bildschirmrand eine Navigationsleiste hinzu, die einen Titel anzeigt, sowie eine für die Plattform geeignete Schaltfläche "Zurück", die zur vorherigen Seite zurückkehrt. Der folgende Code zeigt, wie Sie eine NavigationPage um die erste Seite einer Anwendung wickeln:

Verweise auf den oben aufgeführten Inhalt und einen Link, den Sie überprüfen sollten, um weitere Informationen zu Xamarin-Formularen zu erhalten, siehe Abschnitt "Navigation":

http://developer.xamarin.com/guides/cross-platform/xamarin-forms/introduction-to-xamarin-forms/

~~~

public class MainActivity : AndroidActivity
{
    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);

        Xamarin.Forms.Forms.Init(this, bundle);
        // Set our view from the "main" layout resource
        SetPage(BuildView());
    }

    static Page BuildView()
    {
        var mainNav = new NavigationPage(new RootPage());
        return mainNav;
    }
}


public class RootPage : ContentPage
{
    async void ShowLoginDialog()
    {
        var page = new LoginPage();

        await Navigation.PushModalAsync(page);
    }
}

// Der Code wurde zur Vereinfachung entfernt. Es wird nur der Pop angezeigt 

private async void AuthenticationResult(bool isValid)
{
    await navigation.PopModalAsync();
}
3
Chad Bonthuys

Eine Seite zu einer anderen Seitennavigation in Xamarin.forms mit Navigation property Below Beispielcode 

void addClicked(object sender, EventArgs e)
        {
            //var createEmp = (Employee)BindingContext;
            Employee emp = new Employee();
            emp.Address = AddressEntry.Text;   
            App.Database.SaveItem(emp);
            this.Navigation.PushAsync(new EmployeeDetails());
  this.Navigation.PushModalAsync(new EmployeeDetails());
        }

So navigieren Sie von einer Seite zu einer anderen Seite mit in der Zelle Zelle Unterhalb von Code Xamrian.forms

 private async void BtnEdit_Clicked1(object sender, EventArgs e)
        {
            App.Database.GetItem(empid);
            await App.Current.MainPage.Navigation.PushModalAsync(new EmployeeRegistration(empid));
        }

Beispiel wie unten

public class OptionsViewCell : ViewCell
    {
        int empid;
        Button btnEdit;
        public OptionsViewCell()
        {
        }
        protected override void OnBindingContextChanged()
        {
            base.OnBindingContextChanged();

            if (this.BindingContext == null)
                return;

            dynamic obj = BindingContext;
            empid = Convert.ToInt32(obj.Eid);
            var lblname = new Label
            {
                BackgroundColor = Color.Lime,
                Text = obj.Ename,
            };

            var lblAddress = new Label
            {
                BackgroundColor = Color.Yellow,
                Text = obj.Address,
            };

            var lblphonenumber = new Label
            {
                BackgroundColor = Color.Pink,
                Text = obj.phonenumber,
            };

            var lblemail = new Label
            {
                BackgroundColor = Color.Purple,
                Text = obj.email,
            };

            var lbleid = new Label
            {
                BackgroundColor = Color.Silver,
                Text = (empid).ToString(),
            };

             //var lbleid = new Label
            //{
            //    BackgroundColor = Color.Silver,
            //    // HorizontalOptions = LayoutOptions.CenterAndExpand
            //};
            //lbleid.SetBinding(Label.TextProperty, "Eid");
            Button btnDelete = new Button
            {
                BackgroundColor = Color.Gray,

                Text = "Delete",
                //WidthRequest = 15,
                //HeightRequest = 20,
                TextColor = Color.Red,
                HorizontalOptions = LayoutOptions.EndAndExpand,
            };
            btnDelete.Clicked += BtnDelete_Clicked;
            //btnDelete.PropertyChanged += BtnDelete_PropertyChanged;  

            btnEdit = new Button
            {
                BackgroundColor = Color.Gray,
                Text = "Edit",
                TextColor = Color.Green,
            };
            // lbleid.SetBinding(Label.TextProperty, "Eid");
            btnEdit.Clicked += BtnEdit_Clicked1; ;
            //btnEdit.Clicked += async (s, e) =>{
            //    await App.Current.MainPage.Navigation.PushModalAsync(new EmployeeRegistration());
            //};

            View = new StackLayout()
            {
                Orientation = StackOrientation.Horizontal,
                BackgroundColor = Color.White,
                Children = { lbleid, lblname, lblAddress, lblemail, lblphonenumber, btnDelete, btnEdit },
            };

        }

        private async void BtnEdit_Clicked1(object sender, EventArgs e)
        {
            App.Database.GetItem(empid);
            await App.Current.MainPage.Navigation.PushModalAsync(new EmployeeRegistration(empid));
        }



        private void BtnDelete_Clicked(object sender, EventArgs e)
        {
            // var eid = Convert.ToInt32(empid);
            // var item = (Xamarin.Forms.Button)sender;
            int eid = empid;
            App.Database.DeleteItem(empid);
        }

    }
2
Manohar

Anscheinend ist dieser Thread sehr beliebt und es ist traurig, hier nicht zu erwähnen, dass es einen alternativen Weg gibt - ViewModel First Navigation. Die meisten MVVM-Frameworks verwenden das Programm. Wenn Sie jedoch wissen wollen, worum es geht, lesen Sie weiter.

Die gesamte offizielle Xamarin.Forms-Dokumentation demonstriert eine einfache, aber nicht ganz reine MVVM-Lösung. Das liegt daran, dass Page (View) nichts über ViewModel wissen sollte und umgekehrt. Hier ist ein großartiges Beispiel für diesen Verstoß:

// C# version
public partial class MyPage : ContentPage
{
    public MyPage()
    {
        InitializeComponent();
        // Violation
        this.BindingContext = new MyViewModel();
    }
}

// XAML version
<?xml version="1.0" encoding="utf-8"?>
<ContentPage
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.Microsoft.com/winfx/2009/xaml"
    xmlns:viewmodels="clr-namespace:MyApp.ViewModel"
    x:Class="MyApp.Views.MyPage">
    <ContentPage.BindingContext>
        <!-- Violation -->
        <viewmodels:MyViewModel />
    </ContentPage.BindingContext>
</ContentPage>

Wenn Sie eine 2-seitige Anwendung haben, kann dieser Ansatz für Sie gut sein. Wenn Sie jedoch an einer großen Unternehmenslösung arbeiten, gehen Sie besser mit einem ViewModel First Navigation-Ansatz. Dies ist etwas komplizierter, aber viel sauberer, sodass Sie zwischen ViewModels anstatt zwischen Pages (Ansichten) navigieren können. Ein Vorteil neben der klaren Trennung der Bedenken ist, dass Sie Parameter einfach an das nächste ViewModel übergeben oder gleich nach der Navigation einen asynchronen Initialisierungscode ausführen können. Nun zu den Details.

(Ich werde versuchen, alle Codebeispiele so weit wie möglich zu vereinfachen.) 

1. Zunächst brauchen wir einen Ort, an dem wir alle unsere Objekte registrieren und gegebenenfalls deren Lebensdauer definieren können. Zu diesem Zweck können wir einen IOC Container verwenden, den Sie selbst auswählen können. In diesem Beispiel verwende ich Autofac (es ist eines der schnellsten verfügbaren). Wir können einen Verweis darauf in App behalten, damit er global verfügbar ist (keine gute Idee, aber zur Vereinfachung erforderlich):

public class DependencyResolver
{
    static IContainer container;

    public DependencyResolver(params Module[] modules)
    {
        var builder = new ContainerBuilder();

        if (modules != null)
            foreach (var module in modules)
                builder.RegisterModule(module);

        container = builder.Build();
    }

    public T Resolve<T>() => container.Resolve<T>();
    public object Resolve(Type type) => container.Resolve(type);
}

public partial class App : Application
{
    public DependencyResolver DependencyResolver { get; }

    // Pass here platform specific dependencies
    public App(Module platformIocModule)
    {
        InitializeComponent();
        DependencyResolver = new DependencyResolver(platformIocModule, new IocModule());
        MainPage = new WelcomeView();
    }

    /* The rest of the code ... */
}

2.Wir benötigen ein Objekt, das für das Abrufen einer Page (Ansicht) für ein bestimmtes ViewModel verantwortlich ist, und umgekehrt. Der zweite Fall kann nützlich sein, wenn Sie die Root-/Hauptseite der App festlegen. Dazu sollten wir uns auf eine einfache Konvention einigen, dass alle ViewModels im Verzeichnis ViewModels und Pages (Ansichten) im Verzeichnis Views sein sollten. Mit anderen Worten, ViewModels sollte im [MyApp].ViewModels-Namespace und Pages (Ansichten) im [MyApp].Views-Namespace leben. Darüber hinaus sollten wir uns darauf einigen, dass WelcomeView (Page) WelcomeViewModel usw. haben sollte. Hier ist ein Codebeispiel für einen Mapper:

public class TypeMapperService
{
    public Type MapViewModelToView(Type viewModelType)
    {
        var viewName = viewModelType.FullName.Replace("Model", string.Empty);
        var viewAssemblyName = GetTypeAssemblyName(viewModelType);
        var viewTypeName = GenerateTypeName("{0}, {1}", viewName, viewAssemblyName);
        return Type.GetType(viewTypeName);
    }

    public Type MapViewToViewModel(Type viewType)
    {
        var viewModelName = viewType.FullName.Replace(".Views.", ".ViewModels.");
        var viewModelAssemblyName = GetTypeAssemblyName(viewType);
        var viewTypeModelName = GenerateTypeName("{0}Model, {1}", viewModelName, viewModelAssemblyName);
        return Type.GetType(viewTypeModelName);
    }

    string GetTypeAssemblyName(Type type) => type.GetTypeInfo().Assembly.FullName;
    string GenerateTypeName(string format, string typeName, string assemblyName) =>
        string.Format(CultureInfo.InvariantCulture, format, typeName, assemblyName);
}

3.Für das Setzen einer Stammseite benötigen wir eine Art ViewModelLocator, die BindingContext automatisch setzt:

public static class ViewModelLocator
{
    public static readonly BindableProperty AutoWireViewModelProperty =
        BindableProperty.CreateAttached("AutoWireViewModel", typeof(bool), typeof(ViewModelLocator), default(bool), propertyChanged: OnAutoWireViewModelChanged);

    public static bool GetAutoWireViewModel(BindableObject bindable) =>
        (bool)bindable.GetValue(AutoWireViewModelProperty);

    public static void SetAutoWireViewModel(BindableObject bindable, bool value) =>
        bindable.SetValue(AutoWireViewModelProperty, value);

    static ITypeMapperService mapper = (Application.Current as App).DependencyResolver.Resolve<ITypeMapperService>();

    static void OnAutoWireViewModelChanged(BindableObject bindable, object oldValue, object newValue)
    {
        var view = bindable as Element;
        var viewType = view.GetType();
        var viewModelType = mapper.MapViewToViewModel(viewType);
        var viewModel =  (Application.Current as App).DependencyResolver.Resolve(viewModelType);
        view.BindingContext = viewModel;
    }
}

// Usage example
<?xml version="1.0" encoding="utf-8"?>
<ContentPage
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.Microsoft.com/winfx/2009/xaml"
    xmlns:viewmodels="clr-namespace:MyApp.ViewModel"
    viewmodels:ViewModelLocator.AutoWireViewModel="true"
    x:Class="MyApp.Views.MyPage">
</ContentPage>

4.Schließlich brauchen wir ein NavigationService, das den ViewModel First Navigation-Ansatz unterstützt:

public class NavigationService
{
    TypeMapperService mapperService { get; }

    public NavigationService(TypeMapperService mapperService)
    {
        this.mapperService = mapperService;
    }

    protected Page CreatePage(Type viewModelType)
    {
        Type pageType = mapperService.MapViewModelToView(viewModelType);
        if (pageType == null)
        {
            throw new Exception($"Cannot locate page type for {viewModelType}");
        }

        return Activator.CreateInstance(pageType) as Page;
    }

    protected Page GetCurrentPage()
    {
        var mainPage = Application.Current.MainPage;

        if (mainPage is MasterDetailPage)
        {
            return ((MasterDetailPage)mainPage).Detail;
        }

        // TabbedPage : MultiPage<Page>
        // CarouselPage : MultiPage<ContentPage>
        if (mainPage is TabbedPage || mainPage is CarouselPage)
        {
            return ((MultiPage<Page>)mainPage).CurrentPage;
        }

        return mainPage;
    }

    public Task PushAsync(Page page, bool animated = true)
    {
        var navigationPage = Application.Current.MainPage as NavigationPage;
        return navigationPage.PushAsync(page, animated);
    }

    public Task PopAsync(bool animated = true)
    {
        var mainPage = Application.Current.MainPage as NavigationPage;
        return mainPage.Navigation.PopAsync(animated);
    }

    public Task PushModalAsync<TViewModel>(object parameter = null, bool animated = true) where TViewModel : BaseViewModel =>
        InternalPushModalAsync(typeof(TViewModel), animated, parameter);

    public Task PopModalAsync(bool animated = true)
    {
        var mainPage = GetCurrentPage();
        if (mainPage != null)
            return mainPage.Navigation.PopModalAsync(animated);

        throw new Exception("Current page is null.");
    }

    async Task InternalPushModalAsync(Type viewModelType, bool animated, object parameter)
    {
        var page = CreatePage(viewModelType);
        var currentNavigationPage = GetCurrentPage();

        if (currentNavigationPage != null)
        {
            await currentNavigationPage.Navigation.PushModalAsync(page, animated);
        }
        else
        {
            throw new Exception("Current page is null.");
        }

        await (page.BindingContext as BaseViewModel).InitializeAsync(parameter);
    }
}

Wie Sie sehen, gibt es eine BaseViewModel - abstrakte Basisklasse für alle ViewModels-Methoden, in denen Sie Methoden wie InitializeAsync definieren können, die direkt nach der Navigation ausgeführt werden. Und hier ist ein Beispiel für die Navigation:

public class WelcomeViewModel : BaseViewModel
{
    public ICommand NewGameCmd { get; }
    public ICommand TopScoreCmd { get; }
    public ICommand AboutCmd { get; }

    public WelcomeViewModel(INavigationService navigation) : base(navigation)
    {
        NewGameCmd = new Command(async () => await Navigation.PushModalAsync<GameViewModel>());
        TopScoreCmd = new Command(async () => await navigation.PushModalAsync<TopScoreViewModel>());
        AboutCmd = new Command(async () => await navigation.PushModalAsync<AboutViewModel>());
    }
}

Wie Sie wissen, ist dieser Ansatz komplizierter, schwieriger zu debuggen und kann verwirrend sein. Es gibt jedoch viele Vorteile, und Sie müssen es nicht selbst implementieren, da die meisten MVVM-Frameworks es sofort unterstützen. Das hier gezeigte Codebeispiel ist auf github verfügbar. 

Es gibt viele gute Artikel über ViewModel First Navigation und es gibt ein kostenloses Enterprise Application Patterns mit Xamarin.Forms eBook, das dieses und viele andere interessante Themen ausführlich erklärt.

2
EvZ

Anruf:

((App)App.Current).ChangeScreen(new Map());

Erstellen Sie diese Methode in App.xaml.cs:

public void ChangeScreen(Page page)
{
     MainPage = page;
}
1
alansiqueira27

XAML-Seite fügen Sie dies hinzu 

<ContentPage.ToolbarItems>
            <ToolbarItem Text="Next" Order="Primary"
            Activated="Handle_Activated"/>

</ContentPage.ToolbarItems>   

auf der CS-Seite 

 async void Handle_Activated(object sender, System.EventArgs e)
        {
            await App.Navigator.PushAsync(new PAGE());
        }
0
Pxaml
In App.Xaml.Cs:

MainPage = new NavigationPage( new YourPage());

Wenn Sie von YourPage zur nächsten Seite navigieren möchten, tun Sie Folgendes:

await Navigation.PushAsync(new YourSecondPage());

Weitere Informationen zur Xamarin Forms-Navigation finden Sie hier: https://docs.Microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/navigation/hierarchical

Microsoft hat ziemlich gute Dokumente zu diesem Thema.

Es gibt auch das neuere Konzept des Shell. Es ermöglicht eine neue Strukturierung Ihrer Anwendung und vereinfacht in einigen Fällen die Navigation.

Intro: https://devblogs.Microsoft.com/xamarin/Shell-xamarin-forms-4-0-getting-started/

Video zu den Grundlagen von Shell: https://www.youtube.com/watch?v=0y1bUAcOjZY&t=3112s

Dokumente: https://docs.Microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/Shell/

0