MvvmCross Bindable MonoTouch.Dialog RadioElement

2019-05-31 14:09发布

问题:

I am attempting to create a bindable RadioElement to use in a MonoTouch.Dialog implementation in MvvmCross, and following the pattern in https://github.com/MvvmCross/MvvmCross-Tutorials/tree/master/DialogExamples/DialogExamples.Touch/BindableElements (as suggested in MvvmCross Monotouch.Dialog binding data to a table), I created the following class:

public class MvxBindableRadioElement : RadioElement, IBindableElement
{
    public IMvxBindingContext BindingContext { get; set; }

    public MvxBindableRadioElement ()
    {
        this.CreateBindingContext();

        this.DelayBind(() => {
            var set = this.CreateBindingSet<MvxBindableRadioElement, PropertyCategory>();
            set.Bind().For(me => me.Caption).To(p => p.Id);
            set.Bind().For(me => me.Value).To(p => p.Value);
            set.Apply();
        });
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing) {
            BindingContext.ClearAllBindings();
        }

        base.Dispose(disposing);
    }

    public virtual object DataContext
    {
        get { return BindingContext.DataContext; }
        set { BindingContext.DataContext = value; }
    }
}

PropertyCategory is a basic Model:

public class PropertyCategory
{
    public int Id { get; set; }
    public string Value { get; set; }
}

This is used as follows:

new Section {
    new RootElement ("Category", new RadioGroup ()) {
        new BindableSection<MvxBindableRadioElement> ().Bind(bindings, e => e.ItemsSource, vm => vm.PropertyCategories)
    }.Bind (bindings, e => e.RadioSelected, vm => vm.PropertyCategory) as Element
}

where BindableSection is taken from the MvvmCross repo mentioned above.

Debugging I am able to verify that the newElements variable of MvxBindableSection is correctly populated with MvxBindableRadioElements, but the following error occurs when the TableView.ReloadData() line is executed:

MvxBind:Error: 12.12 Problem seen during binding execution for binding ItemsSource for PropertyCategories - 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) [0x0005c] in /Developer/MonoTouch/Source/mono/mcs/class/corlib/System.Reflection/MonoMethod.cs:238 
at System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) [0x00000] in /Developer/MonoTouch/Source/mono/mcs/class/corlib/System.Reflection/MethodBase.cs:114 
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 <redacted>.iOS.Views.MvxBindableSection`1[<redacted>.Views.MvxBindableRadioElement].NotifyDataSetChanged () [0x000b9] in <redacted>/MonoTouch.Dialog/MvxBindableSection.cs:87 
at <redacted>.iOS.Views.MvxBindableSection`1[<redacted>.Views.MvxBindableRadioElement].SetItemsSource (IEnumerable value) [0x00094] in <redacted>/MonoTouch.Dialog/MvxBindableSection.cs:56 
at <redacted>.iOS.Views.MvxBindableSection`1[<redacted>.Views.MvxBindableRadioElement].set_ItemsSource (IEnumerable value) [0x00003] in <redacted>/MonoTouch.Dialog/MvxBindableSection.cs:30 
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) [0x00044] in /Developer/MonoTouch/Source/mono/mcs/class/corlib/System.Reflection/MonoMethod.cs:230

Troubleshooting this, I replaced the MvxBindableRadioElement with CustomStringElement from the MvvmCross repo mentioned above:

new MvxBindableSection<CustomStringElement>().Bind(bindings, element => element.ItemsSource, vm => vm.PropertyCategories)

This works like a charm. Why does the CustomStringElement work, but not theMvxBindableRadioElement? Do I have to create a bindable RadioGroup that wraps the MvxBindableRadioElements?

EDIT:

Here is the Inner Exception (NullReferenceException):

at CrossUI.Touch.Dialog.Elements.RadioElement.SubscribeToRoot () [0x00000] in <filename unknown>:0 
at CrossUI.Touch.Dialog.Elements.RadioElement.GetCellImpl (MonoTouch.UIKit.UITableView tv) [0x00000] in <filename unknown>:0 
at CrossUI.Touch.Dialog.Elements.Element.GetCell (MonoTouch.UIKit.UITableView tv) [0x00000] in <filename unknown>:0 
at CrossUI.Touch.Dialog.DialogViewController+Source.GetCell (MonoTouch.UIKit.UITableView tableView, MonoTouch.Foundation.NSIndexPath indexPath) [0x00000] in <filename unknown>:0 
at (wrapper managed-to-native) MonoTouch.UIKit.UIApplication:UIApplicationMain (int,string[],intptr,intptr)
at MonoTouch.UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x0004c] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:38 
at PGPCapture.iOS.Application.Main (System.String[] args) [0x00008] in <redacted>/Main.cs:21 

回答1:

OK so the issue was with the implementation of BindableSection (taken from MvvmCross-Tutorials / DialogExamples): the Section element's Parent is not set (i.e. is null) unless you add the elements using AddAll(). This issue actually occurs in the bowels of MT.Dialog itself.

The updated MvxBindableSection is available here.