经过一些测试,以下是建议的解决方案。我不是 100% 爱上它,但它确实有效并提供了我一直在寻找的类型开发人员体验。所以让我们深入研究。
首先,我所有的 ViewModel (VM) 都继承自基础 VM,AVM。此抽象基类支持将对象作为公共静态方法进行查找。这有点恶心,但如果你愿意啜饮 Kool-Aid,它会很有效。以下是与此问题相关的课程部分:
public abstract class AVM : MvxViewModel {
private static readonly Dictionary<Guid, WeakReference> ViewModelCache = new Dictionary<Guid, WeakReference>();
private static readonly string BUNDLE_PARAM_ID = @"AVM_ID";
private Guid AVM_ID = Guid.NewGuid();
private Type MyType;
protected AVM()
{
MyType = this.GetType();
ViewModelCache.Add(AVM_ID, new WeakReference(this));
}
public static bool TryLoadFromBundle(IMvxBundle bundle, out IMvxViewModel viewModel)
{
if (null != bundle && bundle.Data.ContainsKey(BUNDLE_PARAM_ID))
{
var id = Guid.Parse(bundle.Data[BUNDLE_PARAM_ID]);
viewModel = TryLoadFromCache(id);
return true;
}
viewModel = null;
return false;
}
private static IMvxViewModel TryLoadFromCache(Guid Id)
{
if (ViewModelCache.ContainsKey(Id))
{
try
{
var reference = ViewModelCache[Id];
if (reference.IsAlive)
return (IMvxViewModel)reference.Target;
}
catch (Exception exp) { Mvx.Trace(exp.Message); }
}
return null;
}
protected void View()
{
var param = new Dictionary<string, string>();
param.Add(BUNDLE_PARAM_ID, AVM_ID.ToString());
ShowViewModel(MyType, param);
}
为了让这一切都连接起来,您必须创建一个自定义视图模型定位器。这是自定义定位器:
public class AVMLocator : MvxDefaultViewModelLocator
{
public override bool TryLoad(Type viewModelType, IMvxBundle parameterValues, IMvxBundle savedState, out IMvxViewModel viewModel)
{
if (AVM.TryLoadFromBundle(parameterValues, out viewModel))
return true;
return base.TryLoad(viewModelType, parameterValues, savedState, out viewModel);
}
}
最后你必须接线。为此,请进入您的 App.cs 并像这样覆盖 CreateDefaultViewModelLocator:
protected override IMvxViewModelLocator CreateDefaultViewModelLocator()
{
return new AVMLocator();
}
你都准备好了。现在,在任何已经存在且运行良好的派生 ViewModel 中,您可以执行以下操作:
myDerivedVM.View();
我还需要做一些事情(比如确保 WeakReferences 完成他们的工作,并且我没有内存泄漏和一些额外的错误处理),但至少这是我想要的体验。我做的最后一件事是将以下命令添加到 AVM 基类:
public MvxCommand ViewCommand
{
get { return new MvxCommand(View); }
}
现在您可以将该命令绑定到任何 UI 对象,并且在调用时,它将使用该 VM 实例启动该视图。
斯图尔特,感谢您帮助我朝着正确的方向前进。我很想听听您对我提供的解决方案的反馈。感谢您为 MVVMCross 所做的所有工作。这确实是一段非常漂亮的代码。
干杯。