gpt4 book ai didi

xamarin - Caliburn.Micro 3.0 相当于 Xamarin.Forms Navigation.PushModalAsync

转载 作者:行者123 更新时间:2023-12-01 08:53:04 32 4
gpt4 key购买 nike

Caliburn.Micro 3.0(和 Caliburn.Micro.Xamarin.Forms)是否实现了在 Xamarin.Forms 中模拟/支持 Navigation.PushModalAsync 的功能?

最佳答案

没有。它不是内置的,但很容易增强它。通常,MvvM 框架由 ViewModel 导航。 Caliburn 正在遵循这种模式。所以它需要某种导航服务。此导航服务负责为 ViewModel 创建 View 并调用 View 框架(在我们的示例中为 Xamarin.Froms)特定的导航功能。 NavigationPageAdapter是我们正在寻找的东西。现在让我们对其进行增强。

public interface IModalNavigationService : INavigationService
{
Task NavigateModalToViewModelAsync<TViewModel>(object parameter = null, bool animated = true);
// TODO: add more functions for closing
}

public class ModalNavigationPageAdapter : NavigationPageAdapter, IModalNavigationService
{
private readonly NavigationPage _navigationPage;

public ModalNavigationPageAdapter(NavigationPage navigationPage) : base(navigationPage)
{
_navigationPage = navigationPage;
}

public async Task NavigateModalToViewModelAsync<TViewModel>(object parameter = null, bool animated = true)
{
var view = ViewLocator.LocateForModelType(typeof(TViewModel), null, null);

await PushModalAsync(view, parameter, animated);
}

private Task PushModalAsync(Element view, object parameter, bool animated)
{
var page = view as Page;

if (page == null)
throw new NotSupportedException(String.Format("{0} does not inherit from {1}.", view.GetType(), typeof(Page)));

var viewModel = ViewModelLocator.LocateForView(view);

if (viewModel != null)
{
TryInjectParameters(viewModel, parameter);

ViewModelBinder.Bind(viewModel, view, null);
}

page.Appearing += (s, e) => ActivateView(page);
page.Disappearing += (s, e) => DeactivateView(page);

return _navigationPage.Navigation.PushModalAsync(page, animated);
}

private static void DeactivateView(BindableObject view)
{
if (view == null)
return;

var deactivate = view.BindingContext as IDeactivate;

if (deactivate != null)
{
deactivate.Deactivate(false);
}
}

private static void ActivateView(BindableObject view)
{
if (view == null)
return;

var activator = view.BindingContext as IActivate;

if (activator != null)
{
activator.Activate();
}
}
}

我们刚刚声明了接口(interface) IModalNavigationService扩展 INavigationService并在我们的 ModalNavigationPageAdapter 中实现.不幸的是,Caliburn 将许多函数设为私有(private),因此我们必须将它们复制到我们继承的版本中。

在 caliburn,您可以通过 navigationservice.For<VM>().Navigate() 导航.我们想遵循这种风格,所以我们必须实现类似 navigationservice.ModalFor<VM>().Navigate()我们在扩展方法中执行此操作。

public static class ModalNavigationExtensions
{
public static ModalNavigateHelper<TViewModel> ModalFor<TViewModel>(this IModalNavigationService navigationService)
{
return new ModalNavigateHelper<TViewModel>().AttachTo(navigationService);
}
}

此方法返回 ModalNavigateHelper这简化了我们导航服务的使用(类似于 Caliburn 的 NavigateHelper)。它几乎是一个副本,但对于 IModalNavigationService .

public class ModalNavigateHelper<TViewModel>
{
readonly Dictionary<string, object> parameters = new Dictionary<string, object>();
IModalNavigationService navigationService;

public ModalNavigateHelper<TViewModel> WithParam<TValue>(Expression<Func<TViewModel, TValue>> property, TValue value)
{
if (value is ValueType || !ReferenceEquals(null, value))
{
parameters[property.GetMemberInfo().Name] = value;
}

return this;
}

public ModalNavigateHelper<TViewModel> AttachTo(IModalNavigationService navigationService)
{
this.navigationService = navigationService;

return this;
}

public void Navigate(bool animated = true)
{
if (navigationService == null)
{
throw new InvalidOperationException("Cannot navigate without attaching an INavigationService. Call AttachTo first.");
}

navigationService.NavigateModalToViewModelAsync<TViewModel>(parameters, animated);
}
}

最后但同样重要的是,我们必须使用我们 Shiny 的新导航服务而不是旧导航服务。 App类正在注册 NavigationPageAdapter对于INavigationService作为 PrepareViewFirst 中的单例.我们必须改变它如下

public class App : FormsApplication
{
private readonly SimpleContainer container;

public App(SimpleContainer container)
{
this.container = container;

container
.PerRequest<LoginViewModel>()
.PerRequest<FeaturesViewModel>();

Initialize();

DisplayRootView<LoginView>();
}

protected override void PrepareViewFirst(NavigationPage navigationPage)
{
var navigationService = new ModalNavigationPageAdapter(navigationPage);
container.Instance<INavigationService>(navigationService);
container.Instance<IModalNavigationService>(navigationService);
}
}

我们正在为 INavigationService 注册导航服务和 IModalNavigationService .

正如您在评论中看到的,您必须实现调用 PopModalAsync 的关闭函数自己。

关于xamarin - Caliburn.Micro 3.0 相当于 Xamarin.Forms Navigation.PushModalAsync,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36185491/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com