将参数传递给PageRenderer Prism Xamarin Forms

时间:2017-01-13 13:13:48

标签: c# xamarin xamarin.forms prism

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

有人可以为这个问题提出解决方案吗?

1 个答案:

答案 0 :(得分: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
    }
}

编辑: 如果您需要在初始化时设置某些内容,请记住您可以从Renderer访问Container并注入Interface或Concrete类型以访问所需的属性。我将以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
    }