我正在尝试使用Xamarin Form和Prism创建身份验证过程。 我为每个平台创建了 PageRenderer 类,我需要将自定义参数传递给它。试图在ViewModel中使用 INavigationAware 接口,然后从自定义页面访问它,但在 PageRenderer 启动后调用 OnNavigatedTo 方法,因此导航参数仍为空。< / p>
有人可以为这个问题提出解决方案吗?
答案 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
}