首页 文章

将参数传递给PageRenderer Prism Xamarin Forms

提问于
浏览
1

我正在尝试使用Xamarin Form和Prism创建身份验证过程 . 我为每个平台创建了PageRenderer类,我需要将自定义参数传递给它 . 试图在ViewModel中使用INavigationAware接口,然后从自定义页面访问它,但在PageRenderer启动后调用OnNavigatedTo方法,因此导航参数仍为空 .

有谁能建议解决这个问题?

1 回答

  • 2

    有几种方法可以解决这个问题:

    1)如建议的那样使页面INavigationAware并设置您要从PageRenderer访问的属性 . 根据你发送的内容,这当然可以打破MVVM模式 . 但你可以做以下事情:

    创建一个界面

    public interface IMyPage
    {
        string Message { get; set; }
    }
    

    设置ViewModel以处理需要发送到渲染器的参数

    public class MainPageViewModel : BindableBase, INavigationAware
    {
        private string _message;
        public string Message
        {
            get { return _message; }
            set { SetProperty( ref _message, value ); }
        }
    
        public void OnNavigatedTo( NavigationParameters parameters )
        {
            Message = parameters[ "message" ].ToString();
        }
    }
    

    设置页面以实现界面并在页面上创建BindableProperty

    public class MainPage : ContentPage, IMyPage
    {
        public static readonly BindableProperty MessageProperty = BindableProperty.Create( nameof( Message ), typeof( string ), typeof( MainPage ), string.Empty );
    
        public string Message
        {
            get { return (string)GetProperty( MessageProperty ); }
            set { SetProperty( MessageProperty, value ); }
        }
    }
    

    在Xaml标记中,将属性从ViewModel绑定到Bindable属性

    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" 
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 x:Class="MyApplication.Views.MainPage"
                 Message="{Binding Message}">
    </ContentPage>
    

    最后在渲染器处理对属性的更改

    public class MyPageRenderer : PageRenderer
    {
       protected override void OnElementChanged( VisualElementChangedEventArgs e )
        {
            base.OnElementChanged( e );
            // Do foo
        }
    }
    

    请注意,更好的方法是在一个基页类型上实现此功能,使您的页面继承而不是ContentPage或TabbedPage等,然后检查您是否实现了页面接口 .

    2)使用IEventAggregator监听和处理事件 .

    public class MainPageViewModel : INavigationAware
    {
        IEventAggregator _ea { get; }
        public MainPageViewModel( IEventAggregator ea )
        {
            _ea = ea;
        }
    
        public void OnNavigatedTo( NavigationParameters parameters )
        {
            _ea.GetEvent<MyEvent>().Publish( parameters[ "message" ].ToString() );
        }
    }
    
    public class MyPageRenderer : PageRenderer
    {
        public MyPageRenderer()
        {
            var ea = ( App as PrismApplication ).Container.Resolve<IEventAggregator>();
            ea.GetEvent<MyEvent>().Subscribe( OnMyEvent );
        }
    
        public void OnMyEvent( string message )
        {
            // Do what you need to
        }
    }
    

    编辑:如果您需要在初始化时设置某些内容,请记住您可以从渲染器访问Container并注入接口或混凝土类型以访问所需的属性 . 我将以Unity为例 . 这使代码比使用静态属性更容易测试 .

    public class App : PrismApplication
    {
        protected override void RegisterTypes()
        {
            Container.Register<IMySettings,MySettings>( new ContainerControlledLifetimeManager() );
        }
    }
    
    public class MyPageViewModel
    {
        IMySettings _mySettings { get; }
    
        public MyPageViewModel( INavigationService navigationService, IMySettings mySettings )
        {
            _mySettings = mySettings;
            // Update this somewhere in the code before navigating to the new page
        }
    }
    
    public class MyPageRenderer : PageRenderer
    {
        public MyPageRenderer()
        {
            var mySettings = ( App as PrismApplication ).Container.Resolve<IMySettings>();
            // Use MySettings to set the property you need to set
        }
    

相关问题