Xamarin.form Page Navigation in mvvm

前端 未结 8 1062
耶瑟儿~
耶瑟儿~ 2021-02-04 03:52

I am working on xamarin.form cross-platform application , i want to navigate from one page to another on button click. As i cannot do Navigation.PushAsync(new Page2());

相关标签:
8条回答
  • 2021-02-04 04:32

    decided to add two ways to pass Page instance to viewmodel which you can use later for navigation, displaying alerts. closing page and so on.

    1. if you can pass it with command parameter

    in view model:

    public ICommand cmdAddRecord { get; set; }
    

    viewmodel constructor

    cmdAddRecord = new Command<ContentPage>(AddRecord);
    

    somewhere in viewmodel

        void AddRecord(ContentPage parent)
        {
            parent.Navigation.Whatever
        }
    

    XAML

    header

                x:Name="thisPage"
    

    usage

     <ToolbarItem IconImageSource="{StaticResource icAdd}"  Command="{Binding cmdAddRecord}"  CommandParameter="{Binding ., Source={x:Reference thisPage}}" />
    

    2. started using this in my base class for viewmodels

    viewmodel

    public class cMyBaseVm : BindableObject
    

    ...

    public static BindableProperty ParentProperty = BindableProperty.Create("Parent", typeof(ContentPage), typeof(cMyBaseVm), null, BindingMode.OneWay);
    

    ...

       public ContentPage Parent
        {
            get => (ContentPage)GetValue(ParentProperty);
            set => SetValue(ParentProperty, value);
        }
    

    XAML

            xmlns:viewModels="clr-namespace:yournamespace.ViewModels"
            x:Name="thisPage"
    

    and here we go

    <ContentPage.BindingContext>
        <viewModels:cPetEventsListVm Parent="{Binding ., Source={x:Reference thisPage}}" />
    </ContentPage.BindingContext>
    

    child viewmodel

    public class cPetEventsListVm : cMyBaseVm
    

    and now, all around child view model we can use Page like Parent.DisplayAlert , or Parent.Navigation.PushAsync etc we may even close page now from view model with Parent.PopAsync ();

    0 讨论(0)
  • 2021-02-04 04:34

    my approach based on principle every View can navigate to VM context based places of the app only:

    In ViewModel i declare INavigationHandler interfeces like that:

    public class ItemsViewModel : ViewModelBase
    {
        public INavigationHandler NavigationHandler { private get; set; }
    
    
        // some VM code here where in some place i'm invoking
        RelayCommand<int> ItemSelectedCommand => 
            new RelayCommand<int>((itemID) => { NavigationHandler.NavigateToItemDetail(itemID); });
    
    
        public interface INavigationHandler
        {
            void NavigateToItemDetail(int itemID);
        }
    }
    

    And assign code-behind class as INavigationHandler for ViewModel:

    public class ItemsPage : ContentPage, ItemsViewModel.INavigationHandler
    {
        ItemsViewModel viewModel;
    
        public ItemsPage()
        {
            viewModel = Container.Default.Get<ItemsViewModel>();
            viewModel.NavigationHandler = this;
        }
    
    
        public async void NavigateToItemDetail(int itemID)
        {
            await Navigation.PushAsync(new ItemDetailPage(itemID));
        }
    }
    
    0 讨论(0)
提交回复
热议问题