style linebreakmode font example entry xamarin xamarin.forms

linebreakmode - xamarin forms label multiline



¿Cómo se cambian las páginas en formularios Xamarin? (10)

Al utilizar el método PushAsync (), puede presionar y PopModalAsync () puede abrir páginas desde y hacia la pila de navegación. En mi ejemplo de código siguiente, tengo una página de navegación (página raíz) y desde esta página presiono una página de contenido que es una página de inicio de sesión una vez que estoy completo con mi página de inicio de sesión. Vuelvo a la página raíz

~~~ La navegación puede considerarse una pila de objetos de la última entrada y la primera salida. Para pasar de una página a otra, una aplicación insertará una nueva página en esta pila. Para volver a la página anterior, la aplicación mostrará la página actual de la pila. Esta navegación en Xamarin.Forms es manejada por la interfaz de INavigation

Xamarin.Forms tiene una clase NavigationPage que implementa esta interfaz y administrará la pila de páginas. La clase NavigationPage también agregará una barra de navegación en la parte superior de la pantalla que muestra un título y también tendrá un botón Atrás adecuado para la plataforma que regresará a la página anterior. El siguiente código muestra cómo ajustar una NavigationPage alrededor de la primera página en una aplicación:

Referencia al contenido enumerado anteriormente y un enlace que debe revisar para obtener más información sobre los formularios de Xamarin, consulte la sección de navegación:

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); } }

// Código eliminado por simplicidad, solo se muestra el pop

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

¿Cómo cambias entre páginas en formularios Xamarin? Mi página principal es una página de contenido y no quiero cambiar a una página con pestañas.

Pude pseudohacerlo buscando padres de los controles que deberían activar la nueva página hasta que encuentre la página de contenido y luego cambie el contenido por controles para una página nueva. Pero esto parece muy descuidado.

Gracias


En la clase de la aplicación puede establecer la página principal en una página de navegación y establecer la página raíz en su página de contenido:

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

Luego, en su primera llamada a ContentPage:

Navigation.PushAsync (new SecondContentPage ());


Inserta una nueva página en la pila y luego elimina la página actual. Esto resulta en un cambio.

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

Primero debe estar en una página de navegación:

MainPage = NavigationPage(new FirstPage());

Cambiar de contenido no es ideal ya que solo tiene una página grande y un conjunto de eventos de página como OnAppearing ect.


La página XAML agrega esto

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

en la página CS

async void Handle_Activated(object sender, System.EventArgs e) { await App.Navigator.PushAsync(new PAGE()); }


Llamada:

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

Crea este método dentro de App.xaml.cs:

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


Parece que este hilo es muy popular y será triste no mencionar aquí que hay una forma alternativa: la ViewModel First Navigation . La mayoría de los frameworks de MVVM lo usan, sin embargo, si quieres entender de qué se trata, continúa leyendo.

Toda la documentación oficial de Xamarin.Forms está demostrando una solución pura simple, pero ligeramente no MVVM. Eso es porque la Page (vista) no debe saber nada sobre ViewModel y viceversa. Aquí hay un gran ejemplo de esta violación:

// 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>

Si tiene una aplicación de 2 páginas, este enfoque podría ser bueno para usted. Sin embargo, si está trabajando en una solución empresarial grande, es mejor que ViewModel First Navigation enfoque de ViewModel First Navigation . Es un enfoque un poco más complicado pero mucho más limpio que le permite navegar entre ViewModels lugar de navegación entre Pages (Vistas). Una de las ventajas además de la clara separación de preocupaciones es que puede pasar fácilmente parámetros al siguiente ViewModel o ejecutar un código de inicialización asincrónico inmediatamente después de la navegación. Ahora a los detalles.

(Trataré de simplificar todos los ejemplos de código tanto como sea posible).

1. Antes que nada, necesitamos un lugar donde podamos registrar todos nuestros objetos y, opcionalmente, definir su vida útil. Para este asunto, podemos usar un contenedor IOC, usted puede elegir uno usted mismo. En este ejemplo Autofac (es uno de los más rápidos disponibles). Podemos mantener una referencia en la App para que esté disponible globalmente (no es una buena idea, pero es necesaria para simplificar):

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. Necesitaremos un objeto responsable de recuperar una Page (vista) para un ViewModel específico y viceversa. El segundo caso podría ser útil en caso de establecer la página raíz / principal de la aplicación. Para eso deberíamos acordar una convención simple de que todos los ViewModels deberían estar en el directorio ViewModels y las Pages (Vistas) deberían estar en el directorio de Views . En otras palabras, ViewModels debe residir en el espacio de nombres [MyApp].ViewModels y en las Pages (Vistas) en el espacio de nombres [MyApp].Views . Además de eso, debemos aceptar que WelcomeView (Page) debe tener un WelcomeViewModel y etc. Aquí hay un ejemplo de código de un mapeador:

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.Para el caso de establecer una página raíz, necesitaremos una especie de ViewModelLocator que establecerá BindingContext automáticamente:

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. Por último, necesitaremos un NavigationService que sea compatible con el enfoque de ViewModel First Navigation :

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); } }

Como puede ver, hay un BaseViewModel - clase base abstracta para todos los ViewModels donde puede definir métodos como InitializeAsync que se ejecutarán inmediatamente después de la navegación. Y aquí hay un ejemplo de navegación:

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>()); } }

Como usted entiende, este enfoque es más complicado, más difícil de depurar y podría ser confuso. Sin embargo, hay muchas ventajas además de que en realidad no tiene que implementarlo usted mismo, ya que la mayoría de los marcos MVVM lo admiten de manera inmediata. El ejemplo de código que se muestra aquí está disponible en github .

Hay muchos buenos artículos sobre el ViewModel First Navigation de ViewModel First Navigation y hay un Enterprise Application Patterns gratuito que utiliza el eBook Xamarin.Forms que explica este y muchos otros temas interesantes en detalle.


Si no desea ir a la página anterior, es decir, no permita que el usuario regrese a la pantalla de inicio de sesión una vez que se haya completado la autorización, entonces puede usar;

App.Current.MainPage = new HomePage();

Si desea habilitar la funcionalidad de respaldo, solo use

Navigation.PushModalAsync(new HomePage())


Si su proyecto se ha configurado como un proyecto de formularios PCL (y muy probablemente también como formularios compartidos, pero no lo he intentado), hay una clase App.cs que se ve así:

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

puede modificar el método GetMainPage para devolver un nuevo TabbedPaged o alguna otra página que haya definido en el proyecto

Desde allí, puede agregar comandos o controladores de eventos para ejecutar el código y hacer

// 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();


Xamarin.Forms admite múltiples hosts de navegación integrados:

  • NavigationPage , donde se desliza la página siguiente,
  • TabbedPage , el que no te gusta
  • CarouselPage , que permite cambiar a izquierda y derecha a las páginas siguiente / anterior.

Además de esto, todas las páginas también son compatibles con PushModalAsync() que simplemente empuja una nueva página sobre la existente.

Al final, si quiere asegurarse de que el usuario no pueda regresar a la página anterior (usando un gesto o el botón de hardware de respaldo), puede mantener la misma Page visualizada y reemplazar su Content .

Las opciones sugeridas para reemplazar la página raíz también funcionan, pero deberá manejarlas de manera diferente para cada plataforma.


Navegación de una página a otra en Xamarin.forms usando la propiedad de navegación Código de muestra siguiente

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()); }

Para navegar de una página a otra con la celda en la vista A continuación, escriba el código Xamrian.forms

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

Ejemplo como a continuación

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); } }