我正在将带有 Prism 的 xamarin forms 3.x 应用程序迁移到带有 shell 导航的表单 4。
我是否必须创建自定义解决方案才能将复杂的参数传递给新页面,或者 Xamarin 有一些内置功能可以接收字符串参数以外的内容?
谢谢。
我正在将带有 Prism 的 xamarin forms 3.x 应用程序迁移到带有 shell 导航的表单 4。
我是否必须创建自定义解决方案才能将复杂的参数传递给新页面,或者 Xamarin 有一些内置功能可以接收字符串参数以外的内容?
谢谢。
我已经运行了一些似乎有效的测试。我对 Xamarin 比较陌生,因此建议谨慎并欢迎对我可能忽略的任何潜在问题提供任何反馈。
我为 Shell 编写了一个扩展来接受数据对象参数“navigationData”,如下所示:-
await Shell.Current.GoToAsync(state, navigationData, animate);
扩展...
namespace Xamarin.Forms
{
public static class ShellExtensions
{
public static async Task GoToAsync(this Shell shell, ShellNavigationState state, object navigationData, bool animate=false)
{
shell.Navigated += async (sender, e) =>
{
if ((Shell.Current?.CurrentItem?.CurrentItem as IShellSectionController)?.PresentedPage is MyContentPage
p) await p.InitializeAsync(navigationData).ConfigureAwait(false);
};
await shell.GoToAsync(state, animate);
}
}
}
如上图所示:-
在上面的扩展方法中,'MyContentPage' 是 ContentPage 的一个自定义抽象子类,它具有一个 InitializeAsync(navigationData) 方法,该方法简单地调用 viewModel 上的类似方法(视图的绑定上下文)。同样,ViewModels 子类化了具有虚拟 InitializeAsync(navigationData) 的自定义 ViewModelBase 类。这可以在 viewModel 中使用所需的实现和导航数据处理来覆盖。
视图、视图模型和相关基类的简化示例如下所示
using System.Threading.Tasks;
using MyXamarinApp.ViewModels;
using Xamarin.Forms;
namespace MyXamarinApp.Views
{
public ItemDetailPage : MyContent<ItemDetailViewModel>{}
public ItemPage : MyContentPage<ItemViewModel>{}
public abstract class MyContentPage<T> : MyContentPage where T : ViewModelBase
{
protected T Vm;
protected override ViewModelBase VmBase => Vm as ViewModelBase;
protected MyContentPage()
{
BindingContext = Vm = ViewModelLocator.Resolve<T>();
}
private Comand _showDetailCommand;
public Command ShowDetailCommand
{
get { return _showDetailCommand ??= new Command(async () =>
await Shell.Current.GoToAsync("itemDetail", new NavigationDataObject())); }
}
}
public abstract class MyContentPage : ContentPage
{
protected abstract ViewModelBase VmBase { get; }
public virtual async Task InitializeAsync(object navigationData)
{
await VmBase.InitializeAsync(navigationData);
}
}
}
public class NavigationDataObject
{
'Properties' etc.
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
namespace MyXamarinApp.ViewModels
{
public ItemViewModel : ViewModelBase{}
public ItemDetailViewModel : ViewModelBase
{
private NavigationDataObject _navData;
public override async Task InitializeAsync(object navigationData)
{
if (navigationData is NavigationDataObject navData)
{
_navData = navData;
}
await base.InitializeAsync(navigationData);
}
}
public abstract class ViewModelBase
{
public virtual Task InitializeAsync(object navigationData)
{
return Task.FromResult(false);
}
}
}
您总是可以将模型序列化为 JSON 字符串并在另一端取消序列化它吗?
async void Handle_ItemTapped(object sender, ItemTappedEventArgs e)
{
if (e.Item == null)
return;
DailyPnL PnLClicked = (DailyPnL)e.Item;
string jason = await Task.Run(() => JsonConvert.SerializeObject(PnLClicked));
await Shell.Current.GoToAsync($"viewdailypnl?pnlmodel={jason}");
//Deselect Item
((ListView)sender).SelectedItem = null;
}
然后在你的代码后面:
public string pnlmodel
{
set
{
string derulo = Uri.UnescapeDataString(value);
viewModel.PnL = Task.Run(() => JsonConvert.DeserializeObject<DailyPnL>(derulo)).Result;
}
}
有一个名为Xamarin.Zero
https://github.com/markjackmilian/Xam.Zero的框架
,它允许您使用 shell,同时为您提供方便的 ViewModel 到 ViewModel 导航,IOC。