Xamarin.android 为什么将头视图添加到MvxListView派生视图会中断绑定过程?
我目前正在为新的应用程序项目使用MvvmCross,并且我正在尝试使用MvxListView显示标题视图。通过阅读讨论(如),我了解到在设置适配器之后无法添加headerview,因此必须重写构造函数,以便在设置MVXAAdapter之前添加header。这使我实现了以下类:Xamarin.android 为什么将头视图添加到MvxListView派生视图会中断绑定过程?,xamarin.android,xamarin,mvvmcross,Xamarin.android,Xamarin,Mvvmcross,我目前正在为新的应用程序项目使用MvvmCross,并且我正在尝试使用MvxListView显示标题视图。通过阅读讨论(如),我了解到在设置适配器之后无法添加headerview,因此必须重写构造函数,以便在设置MVXAAdapter之前添加header。这使我实现了以下类: public class HeaderListView : MvxListView { public FrameLayout HeaderFrame { get; set; } public Header
public class HeaderListView : MvxListView
{
public FrameLayout HeaderFrame { get; set; }
public HeaderListView(Context context, IAttributeSet attrs)
: this(context, attrs, new MvxAdapter(context))
{
}
public HeaderListView(Context context, IAttributeSet attrs, IMvxAdapter adapter)
: base(context, attrs, null)
{
InitializeHeader(context);
// Note: Any calling derived class passing a null adapter is responsible for setting
// it's own itemTemplateId
if (adapter == null)
return;
var itemTemplateId = MvxAttributeHelpers.ReadListItemTemplateId(context, attrs);
adapter.ItemTemplateId = itemTemplateId;
Adapter = adapter;
}
private void InitializeHeader(Context context)
{
HeaderFrame = new FrameLayout(context);
AddHeaderView(HeaderFrame);
}
}
特别注意第二个构造函数中的InitializeHeader调用。当我注释掉这一行时,测试应用程序启动良好,这个HeaderListView的行为与标准的MvxListView没有区别。但是,如果取消对该行的注释,您将看到一个空白的ListView和一些绑定错误:
MvxBind:Error: 10.86 Problem seen during binding execution for binding ItemsSource for Names - problem TargetInvocationException: Exception has been thrown by the target of an invocation.
02-02 23:33:01.948 I/mono-stdout( 2323): MvxBind:Error: 10.86 Problem seen during binding execution for binding ItemsSource for Names - problem TargetInvocationException: Exception has been thrown by the target of an invocation.
at System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] in <filename unknown>:0
at System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) [0x00000] in <filename unknown>:0
at Cirrious.MvvmCross.Binding.Bindings.Target.MvxPropertyInfoTargetBinding.SetValueImpl (System.Object target, System.Object value) [0x00000] in <filename unknown>:0
02-02 23:33:01.948 I/mono-stdout( 2323): at System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] in <filename unknown>:0
02-02 23:33:01.948 I/mono-stdout( 2323): at System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) [0x00000] in <filename unknown>:0
02-02 23:33:01.958 I/mono-stdout( 2323): at Cirrious.MvvmCross.Binding.Bindings.Target.MvxPropertyInfoTargetBinding.SetValueImpl (System.Object target, System.Object value) [0x00000] in <filename unknown>:0
at Cirrious.MvvmCross.Binding.Bindings.Target.MvxConvertingTargetBinding.SetValue (System.Object value) [0x00000] in <filename unknown>:0
at Cirrious.MvvmCross.Binding.Bindings.MvxFullBinding.UpdateTargetFromSource (System.Object value) [0x00000] in <filename unknown>:0
InnerException was NullReferenceException: Object reference not set to an instance of an object
at Cirrious.MvvmCross.Binding.Droid.Views.MvxListView.set_ItemsSource (IEnumerable value) [0x00000] in <filename unknown>:0
at (wrapper managed-to-native) System.Reflection.MonoMethod:InternalInvoke (System.Reflection.MonoMethod,object,object[],System.Exception&)
02-02 23:33:01.958 I/mono-stdout( 2323): at Cirrious.MvvmCross.Binding.Bindings.Target.MvxConvertingTargetBinding.SetValue (System.Object value) [0x00000] in <filename unknown>:0
02-02 23:33:01.968 I/mono-stdout( 2323): at Cirrious.MvvmCross.Binding.Bindings.MvxFullBinding.UpdateTargetFromSource (System.Object value) [0x00000] in <filename unknown>:0
02-02 23:33:01.968 I/mono-stdout( 2323): InnerException was NullReferenceException: Object reference not set to an instance of an object
02-02 23:33:01.968 I/mono-stdout( 2323): at Cirrious.MvvmCross.Binding.Droid.Views.MvxListView.set_ItemsSource (IEnumerable value) [0x00000] in <filename unknown>:0
02-02 23:33:01.968 I/mono-stdout( 2323): at (wrapper managed-to-native) System.Reflection.MonoMethod:InternalInvoke (System.Reflection.MonoMethod,object,object[],System.Exception&)
at System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] in <filename unknown>:0
MvxBind:Error:10.86在绑定项的绑定执行期间发现问题名称的源-问题TargetInvocationException:调用的目标已引发异常。
02-02 23:33:01.948 I/mono标准输出(2323):MvxBind:错误:10.86在绑定项的绑定执行过程中发现问题名称来源-问题TargetInvocationException:调用的目标已引发异常。
在System.Reflection.MonMethod.Invoke(System.Object obj、BindingFlags invokeAttr、System.Reflection.Binder Binder、System.Object[]参数、System.Globalization.CultureInfo区域性)[0x00000]中:0
在System.Reflection.MethodBase.Invoke(System.Object obj,System.Object[]参数)[0x00000]中:0
在Cirries.MvvmCross.Binding.Bindings.Target.MvxPropertyInfoTargetBinding.SetValueImpl(System.Object目标,System.Object值)[0x00000]处,输入:0
02-02 23:33:01.948 I/mono标准输出(2323):在System.Reflection.MonoMethod.Invoke(System.Object obj,BindingFlags invokeAttr,System.Reflection.Binder Binder,System.Object[]参数,System.Globalization.CultureInfo文化)[0x00000]中:0
02-02 23:33:01.948 I/mono标准输出(2323):位于System.Reflection.MethodBase.Invoke(System.Object obj,System.Object[]参数)[0x00000]中:0
02-02 23:33:01.958 I/mono标准输出(2323):在cirrius.MvvmCross.Binding.Bindings.Target.MvxPropertyInfoTargetBinding.SetValueImpl(System.Object目标,System.Object值)[0x00000]中:0
在Cirriary.MvvmCross.Binding.Bindings.Target.MvxConvertingTargetBinding.SetValue(System.Object值)[0x00000]处,输入:0
在cirrium.MvvmCross.Binding.Bindings.MvxFullBinding.UpdateTargetFromSource(System.Object值)[0x00000]中:0
InnerException为NullReferenceException:对象引用未设置为对象的实例
在cirriary.MvvmCross.Binding.Droid.Views.MvxListView.set_ItemsSource(IEnumerable value)[0x00000]中:0
at(包装器管理为本机)System.Reflection.monmethod:InternalInvoke(System.Reflection.monmethod,object,object[],System.Exception&)
02-02 23:33:01.958 I/mono标准输出(2323):在cirrius.MvvmCross.Binding.Bindings.Target.MvxConvertingTargetBinding.SetValue(System.Object值)[0x00000]中:0
02-02 23:33:01.968 I/mono标准输出(2323):在cirrium.MvvmCross.Binding.Bindings.MvxFullBinding.UpdateTargetFromSource(System.Object值)[0x00000]中:0
02-02 23:33:01.968 I/mono标准输出(2323):InnerException为NullReferenceException:对象引用未设置为对象的实例
02-02 23:33:01.968 I/mono标准输出(2323):在cirriary.MvvmCross.Binding.Droid.Views.MvxListView.set_ItemsSource(IEnumerable value)[0x00000]in:0
02-02 23:33:01.968 I/mono标准输出(2323):at(包装器管理为本机)System.Reflection.monmethod:InternalInvoke(System.Reflection.monmethod,object,object[],System.Exception&)
在System.Reflection.MonMethod.Invoke(System.Object obj、BindingFlags invokeAttr、System.Reflection.Binder Binder、System.Object[]参数、System.Globalization.CultureInfo区域性)[0x00000]中:0
我完全无法理解这个错误,因为导致它出现的唯一区别是我在分配适配器之前分配了一个标题视图,但这与适配器没有任何关系。此错误的来源是什么?我如何解决它
演示此问题的示例项目的完整来源是可用的。我看不出错误背后的任何明显原因 看起来“绑定过程”没有从跟踪中断。相反,看起来适配器不知何故卡在了
null
有一个建议有助于进一步调试—如果您向自定义列表视图添加一个新的ItemsSource,那么这将用于绑定—并将为您提供放置断点的位置,以便您可以在设置\u ItemsSource
空引用问题期间调查ListView控件的状态
[MvxSetToNullAfterBinding]
public new IEnumerable ItemsSource
{
get { return Adapter.ItemsSource; }
set {
// here is where null is being reported
// add a breakpoint and examine Adapter and ((ListView)this).Adapter in the watch window
Adapter.ItemsSource = value;
}
}
除此之外,您还可以尝试将所有MvxListView代码复制到视图中,看看这是否有助于识别问题。原因与将页眉和页脚添加到ListView的方式有关。将页眉或页脚添加到列表视图时,为列表视图设置适配器时,它会将适配器包装在HeaderViewListAdapter中,该适配器将返回页眉和页脚,就像它们只是适配器返回的实际行之前和之后的行一样 MvxListView失败的原因是它的Adpater属性,如下所示:
public new IMvxAdapter Adapter
{
get { return base.Adapter as IMvxAdapter; }
set
{
// Code to copy ItemsSource and template ID
base.Adapter = value;
}
}
它不存储您提供的IMvxAdapter实例。它只是在base.Adapter中设置它,并期望在稍后获得base.Adapter时,它将与之前设置的值相同。但如果将页眉和页脚添加到列表中,则情况并非如此。从base.Adapter返回的类将是一个HeadServiceWlistAdapter,它封装了前面设置的IMvxAdapter实例
作为MvxList的用户,没有解决这个问题的好方法(除了复制和更改MvxList)。Stuart的解决方案是不依赖getter的base.Adapter,而是将值存储到setter中的一个字段中并返回tha