#c# #xamarin.forms
#c# #xamarin.forms
Вопрос:
Я набираю скорость в Xamarin. Я использую «Освоение Xamarin.Формы: методы архитектуры приложений для создания многоплатформенных собственных мобильных приложений с помощью Xamarin.Формы 4, 3-е издание» в качестве руководства. Это заставило меня создать пользовательский сервис навигации.
Вот реализация (я пропустил интерфейс для краткости)
namespace wfw_dispenser.Services
{
public class XamarinFormsNavService : INavService
{
readonly IDictionary<Type, Type> _map = new Dictionary<Type, Type>();
public event PropertyChangedEventHandler CanGoBackChanged;
public INavigation XamarinFormsNav { get; set; }
public bool CanGoBack => XamarinFormsNav.NavigationStack?.Any() == true;
public async Task GoBack()
{
if (CanGoBack)
{
await XamarinFormsNav.PopAsync(true);
OnCanGoBackChanged();
}
}
public async Task NavigateTo<TVM>()
where TVM : BaseViewModel
{
await NavigateToView(typeof(TVM));
if (XamarinFormsNav.NavigationStack.Last().BindingContext is BaseViewModel)
{
((BaseViewModel)XamarinFormsNav.NavigationStack.Last().BindingContext).Init();
}
}
public async Task NavigateTo<TVM, TParameter>(TParameter parameter)
where TVM : BaseViewModel
{
await NavigateToView(typeof(TVM));
if (XamarinFormsNav.NavigationStack.Last().BindingContext is BaseViewModel<TParameter>)
{
((BaseViewModel<TParameter>)XamarinFormsNav.NavigationStack.Last().BindingContext).Init(parameter);
}
}
public void RemoveLastView()
{
if (XamarinFormsNav.NavigationStack.Count< 2)
{
return;
}
var lastView = XamarinFormsNav.NavigationStack[XamarinFormsNav.NavigationStack.Count - 2];
XamarinFormsNav.RemovePage(lastView);
}
public void ClearBackStack()
{
if (XamarinFormsNav.NavigationStack.Count < 2)
{
return;
}
for (var i = 0; i < XamarinFormsNav.NavigationStack.Count - 1; i )
{
XamarinFormsNav.RemovePage(XamarinFormsNav.NavigationStack[i]);
}
}
public void NavigateToUri(Uri uri)
{
if (uri == null)
{
throw new ArgumentException("Invalid URI");
}
Device.OpenUri(uri);
}
async Task NavigateToView(Type viewModelType)
{
if (!_map.TryGetValue(viewModelType, out Type viewType))
{
throw new ArgumentException("No view found in view mapping for " viewModelType.FullName ".");
}
// Use reflection to get the View's constructor and create an instance of the View
var constructor = viewType.GetTypeInfo()
.DeclaredConstructors
.FirstOrDefault(dc => !dc.GetParameters().Any());
var view = constructor.Invoke(null) as Page;
var vm = ((App)Application.Current).Kernel.GetService(viewModelType);
view.BindingContext = vm;
await XamarinFormsNav.PushAsync(view, true);
}
public void RegisterViewMapping(Type viewModel, Type view)
{
_map.Add(viewModel, view);
}
void OnCanGoBackChanged() => CanGoBackChanged?.Invoke(this, new PropertyChangedEventArgs("CanGoBack"));
}
}
Мне кажется, что есть NavigateTo, который принимает параметр. Я попробовал это, и это вроде как никуда не уходит без каких-либо ошибок в журнале. В тексте об этом методе нет ничего, объясняющего, как его использовать.
Вероятно, для этого мне нужно что-то сделать в «перехватывающей» модели представления. Кто-нибудь может мне помочь?
Комментарии:
1. смотрите
BaseViewModel<T>
— github.com/edsnider/mastering-xamarin.forms-book/blob /…2. @Jason, Ах, пропустил это. Итак, я просто реализую этот метод в своем конкретном классе?
3. Также вы можете написать свою проверку типов короче с помощью сопоставления с образцом:
if (XamarinFormsNav.NavigationStack.Last().BindingContext is BaseViewModel baseVM) { baseVM.Init(); }
Ответ №1:
Во-первых, вы должны перейти от параметризованной версии BaseViewModel. В вашем случае, поскольку вы передаете в a PaymentRequest
, это будет:
public class CheckoutViewModel : BaseViewModel<PaymentRequest>
Затем BaseViewModel<T>
есть виртуальный Init
метод, который вы можете реализовать
public class BaseViewModel<TParameter> : BaseViewModel
{
protected BaseViewModel(INavService navService, IAnalyticsService analyticsService)
: base(navService, analyticsService)
{
}
public override void Init()
{
Init(default(TParameter));
}
public virtual void Init(TParameter parameter)
{
}
}