问题描述
在解决了上一边博客的问题之后,在进行后续的操作时竟然在XX-XXViewModel中使用this.GetView()返回的是null😓!!!
这篇博客跟上一篇博客可谓是联系紧密。现在做的项目是在之前同事做的项目中分离出来的,当然就少不了Ctrl+C、Ctrl+V的操作。在经历了一番代码搬运和修改之后,发现某个方法使用了this.GetView(),调试的时候该方法返回null。
在this.GetView()处按F12可以找到ViewAware的类。
#region 程序集 Caliburn.Micro.dll, v0.0.0.0
//Caliburn.Micro.dll
#endregion
using System;
using System.Collections.Generic;
namespace Caliburn.Micro
{
public class ViewAware : PropertyChangedBase, IViewAware
{
public static bool CacheViewsByDefault;
protected readonly Dictionary<object, object> Views;
public ViewAware();
public ViewAware(bool cacheViews);
protected bool CacheViews { get; set; }
public event EventHandler<ViewAttachedEventArgs> ViewAttached;
public virtual object GetView(object context = null);
protected virtual void OnViewAttached(object view, object context);
protected virtual void OnViewLoaded(object view);
}
}
注意XX-XXViewModel中实现了Screen。
#region 程序集 Caliburn.Micro.dll, v0.0.0.0
// Caliburn.Micro.dll
#endregion
using System;
using System.ComponentModel;
namespace Caliburn.Micro
{
public class Screen : ViewAware, IScreen, IHaveDisplayName, IActivate, IDeactivate, IGuardClose, IClose, INotifyPropertyChangedEx, INotifyPropertyChanged, IChild
{
public Screen();
public string DisplayName { get; set; }
public bool IsActive { get; }
public bool IsInitialized { get; }
public object Parent { get; set; }
public event EventHandler<ActivationEventArgs> Activated;
public event EventHandler<DeactivationEventArgs> AttemptingDeactivation;
public event EventHandler<DeactivationEventArgs> Deactivated;
public virtual void CanClose(Action<bool> callback);
protected virtual void OnActivate();
protected virtual void OnDeactivate(bool close);
protected virtual void OnInitialize();
public virtual void TryClose();
public virtual void TryClose(bool? dialogResult);
}
}
在这里可以看到ViewAware实现了PropertyChangedBase和IViewAware的接口,其中CM提供了IViewAware来允许在ViewModel中缓存(Cache)对应的View。
ViewAware是IViewAware的默认实现类。当ViewModel和View被绑定到一起后,IViewAware的AttachView方法被调用,你可以重载OnViewAttached方法来针对View做一定处理,如注册View的事件(要小心事件的强引用)。当View被加载到VirualTree后,ViewAware的OnViewLoaded方法被调用,可以在这里遍历View的VisualTree做相应处理。
ViewLocator调用LocateForModel时也会首先判断ViewModel是不是实现了IViewAware并且已经缓存了View,如果是,那么不重新生成View而是直接返回缓存的View。此处引用
看了一下写好的View和ViewModel,更疑惑了,我的写法是正确的呀😭。
充满困惑的我用画图工具画了下面这张图,盯着这张图进行了几分钟的头脑风暴🧐。
忽然灵机一动想到了解决方案。
在XXViewModel中定义了XX-XXView,并对其进行了赋值。那不就说明这个XX-XXView就可以直接拿来使用,它就相当于是XX-XXViewModel中的this.GetView()方法获取到的那个View,然后呢,就可以进行后续的操作了。
一顿操作猛如虎,回想当初的错误,太Low了😂。不过在寻找解决方法的过程中,也了解到了更多的东西。