Generics 如何按照Xamarin.Forms中的MVVM架构进行导航,而不使用任何框架,如PRISM或任何导航服务?
我有一个继承了PageBase.xaml的LoginPage.xamlLoginViewModel是LoginPage的ViewModel,它继承了BASEWMODELBaseViewModel具有定义的Func委托-OnModalNavigationRequest,该委托由PageBase在其OnAppearing方法中订阅,实现在HandleModalNavigationRequest方法中提供。单击Login按钮LoginPage.xaml时,调用LoginViewModel的OnSubmit方法,绑定通过命令,该命令在成功身份验证后调用navigateTomodel方法BaseViewModelNavigateToModel方法BaseViewModel在检查是否为null后,调用HandleModelNavigationRequest方法PageBase上的delegateOnModelNavigationRequest 我的问题是,OnModalNavigationRequest总是以null的形式出现,这表明它没有订户。这意味着未调用PageBase的OnAppearing方法,这意味着未实例化PageBase。如何解决这个问题 我正在发布正在发生的事件顺序代码: 免责声明:代码帮助已从 App.xaml.csGenerics 如何按照Xamarin.Forms中的MVVM架构进行导航,而不使用任何框架,如PRISM或任何导航服务?,generics,mvvm,xamarin.forms,navigation,func,Generics,Mvvm,Xamarin.forms,Navigation,Func,我有一个继承了PageBase.xaml的LoginPage.xamlLoginViewModel是LoginPage的ViewModel,它继承了BASEWMODELBaseViewModel具有定义的Func委托-OnModalNavigationRequest,该委托由PageBase在其OnAppearing方法中订阅,实现在HandleModalNavigationRequest方法中提供。单击Login按钮LoginPage.xaml时,调用LoginViewModel的OnSubm
protected override void OnStart()
{
// Handle when your app starts
var properties = Current.Properties;
if (properties.ContainsKey("Username"))
{
if (properties["Username"] != null)
{
var loggedInUser = (string)properties["Username"];
MainPage = new MainPage();
}
else
{
MainPage = new LoginPage();
}
}
else
{
MainPage = new LoginPage();
}
}
public partial class PageBase<TViewModel> : ContentPage, IView<TViewModel> where TViewModel : BaseViewModel, new()
{
public TViewModel ViewModel
{
get
{
return GetValue(BindingContextProperty) as TViewModel;
}
set
{
SetValue(BindingContextProperty, value);
}
}
#region <Events>
protected override void OnAppearing()
{
base.OnAppearing();
ViewModel.OnModalNavigationRequest = HandleModalNavigationRequest;
}
protected override void OnDisappearing()
{
base.OnDisappearing();
ViewModel.OnModalNavigationRequest = null;
}
#endregion
async Task HandleModalNavigationRequest(BaseViewModel targetViewModel)
{
var targetView = ViewResolver.GetViewFor(targetViewModel);
targetView.BindingContext = targetViewModel;
await Navigation.PushModalAsync(new NavigationPage(targetView));
}
}
public partial class LoginPage : PageBase
{
LoginViewModel ViewModel => BindingContext as LoginViewModel;
public LoginPage() : base()
{
BindingContext = new LoginViewModel();
InitializeComponent();
}
}
public class LoginViewModel : BaseViewModel
{
public Command SubmitCommand { protected set; get; }
public LoginViewModel() : base()
{
Title = "Login";
SubmitCommand = new Command(async () => await OnSubmit());
}
public async Task OnSubmit()
{
await NavigateToModal<ItemsViewModel>(new ItemsViewModel());
}
}
IView
public interface IView
{
}
public interface IView<TViewModel> : IView where TViewModel : BaseViewModel
{
TViewModel ViewModel { get; set; }
}
LoginViewModel.cs
protected override void OnStart()
{
// Handle when your app starts
var properties = Current.Properties;
if (properties.ContainsKey("Username"))
{
if (properties["Username"] != null)
{
var loggedInUser = (string)properties["Username"];
MainPage = new MainPage();
}
else
{
MainPage = new LoginPage();
}
}
else
{
MainPage = new LoginPage();
}
}
public partial class PageBase<TViewModel> : ContentPage, IView<TViewModel> where TViewModel : BaseViewModel, new()
{
public TViewModel ViewModel
{
get
{
return GetValue(BindingContextProperty) as TViewModel;
}
set
{
SetValue(BindingContextProperty, value);
}
}
#region <Events>
protected override void OnAppearing()
{
base.OnAppearing();
ViewModel.OnModalNavigationRequest = HandleModalNavigationRequest;
}
protected override void OnDisappearing()
{
base.OnDisappearing();
ViewModel.OnModalNavigationRequest = null;
}
#endregion
async Task HandleModalNavigationRequest(BaseViewModel targetViewModel)
{
var targetView = ViewResolver.GetViewFor(targetViewModel);
targetView.BindingContext = targetViewModel;
await Navigation.PushModalAsync(new NavigationPage(targetView));
}
}
public partial class LoginPage : PageBase
{
LoginViewModel ViewModel => BindingContext as LoginViewModel;
public LoginPage() : base()
{
BindingContext = new LoginViewModel();
InitializeComponent();
}
}
public class LoginViewModel : BaseViewModel
{
public Command SubmitCommand { protected set; get; }
public LoginViewModel() : base()
{
Title = "Login";
SubmitCommand = new Command(async () => await OnSubmit());
}
public async Task OnSubmit()
{
await NavigateToModal<ItemsViewModel>(new ItemsViewModel());
}
}
public类LoginViewModel:BaseViewModel
{
公共命令SubmitCommand{protected set;get;}
public LoginViewModel():base()
{
Title=“登录”;
SubmitCommand=new命令(async()=>await OnSubmit());
}
公共异步任务OnSubmit()
{
等待NavigateTomodel(新的ItemsViewModel());
}
}
通过
<views:PageBase xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:views="clr-namespace:IPMS.Views.Shared;assembly=IPMS"
xmlns:ViewModel="clr-namespace:IPMS.ViewModels.Shared;assembly=IPMS"
x:Class="IPMS.Views.Shared.LoginPage"
x:TypeArguments="ViewModel:LoginViewModel"
BackgroundImageSource="loginbg.9.jpg"
Title="{Binding Title}">
</views:PageBase>
public partial class LoginPage : PageBase<LoginViewModel>
{
public LoginPage() : base()
{
BindingContext = new LoginViewModel();
InitializeComponent();
}
}
<views:PageBase xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:views="clr-namespace:IPMS.Views.Shared;assembly=IPMS"
xmlns:ViewModel="clr-namespace:IPMS.ViewModels.Shared;assembly=IPMS"
x:Class="IPMS.Views.Shared.LoginPage"
x:TypeArguments="ViewModel:LoginViewModel"
BackgroundImageSource="loginbg.9.jpg"
Title="{Binding Title}">
</views:PageBase>
public partial class LoginPage : PageBase<LoginViewModel>
{
public LoginPage() : base()
{
BindingContext = new LoginViewModel();
InitializeComponent();
}
}
public分部类登录页面:PageBase
{
public LoginPage():base()
{
BindingContext=新的LoginViewModel();
初始化组件();
}
}
,根据这篇文章,我发现作者提供的东西很简单,所以你会尝试作者的样本吗?是的,但样本中不包括从PageBase.xaml继承的页面,这就是我面临的挑战,因为在一些链接中,我们无法继承xaml,而我刚刚开始使用Xamarin,我不知道x:TypeArguments是做什么的。很高兴听到您自己解决了问题,所以请记住将您的回答标记为答案,谢谢。