1

我有很多片段,在布局中 90% 是常见的。因为我真的很喜欢代码布局(我不再为 iOS 创建 XIB),所以我想:让我们为 Android 做同样的事情。这并不像我想象的那么容易。问题出在 MvvmCross 中,在网上搜索解决方案后,只能找到指向解决方案的提示。

问题:当显示片段并执行绑定时,我收到所有消息,源属性无法找到,因为它试图绑定到空对象。

Unable to bind: source property source not found Cirrious.MvvmCross.Binding.Parse.PropertyPath.PropertyTokens.MvxPropertyNamePropertyToken on null-object

布局显示在屏幕上,设置了 ViewModel,设置了绑定上下文(都是我自己创建的,因为这不是自动完成的)。

我怀疑在通货膨胀中做了一些事情来“注册”创建的控件,并且因为我不使用通货膨胀,所以它们没有被注册。我阅读了有关 MvxBindingContextStackRegistration 的其他问题,并查看了相关来源。第二个原因可能是 bindingcontext 本身:不知何故,它没有自动处理,这表明在下面的代码中调用了一些必要的缺失 beging。

我可能做了一些奇怪的事情,因为这是让它工作的最后尝试:

    public class IndexTocFragment : MvxFragment
{
            // two statics to save on typing
    public static int WRAP = ViewGroup.LayoutParams.WrapContent;
    public static int FILL = ViewGroup.LayoutParams.FillParent;
    public LinearLayout NewVerticalLinearLayout(Orientation orientation, Boolean fillparent) {
        var ll = new LinearLayout (Activity) { Orientation = orientation };
        ll.LayoutParameters = new ViewGroup.LayoutParams (FILL, fillparent ? FILL : WRAP);
        return ll;
    }


    public new IndexTocViewModel ViewModel { get { return base.ViewModel as IndexTocViewModel; } set { base.ViewModel = value; } } 

    public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        base.OnCreateView (inflater, container, savedInstanceState);

        var layout = NewVerticalLinearLayout (Orientation.Vertical, true);


        if (ViewModel == null)
            ViewModel = Mvx.IocConstruct<IndexTocViewModel> ();
        BindingContext = new MvxAndroidBindingContext (Activity, new MvxSimpleLayoutInflater(inflater));
        using (new MvxBindingContextStackRegistration<IMvxAndroidBindingContext>(((IMvxAndroidBindingContext) this.BindingContext)))
        {
            //var layout = NewVerticalLinearLayout (Orientation.Vertical, true);
            layout.SetBackgroundColor (Color.ParseColor("#FFFFFF"));
            var titlelayer = NewVerticalLinearLayout (Orientation.Horizontal, false);
            titlelayer.LayoutParameters.Height = 40;
            var title = new TextView (Activity) { LayoutParameters = new ViewGroup.LayoutParams (FILL, FILL) };
            title.SetTextColor (Color.ParseColor ("#212121"));
            var titlebutton = new Button (Activity) { LayoutParameters = new ViewGroup.LayoutParams (WRAP, FILL) };
            titlelayer.AddView (title);
            titlelayer.AddView (titlebutton);
            layout.AddView (titlelayer);

            var twobuttonlayer = NewVerticalLinearLayout (Orientation.Horizontal, false);
            twobuttonlayer.LayoutParameters.Height = 40;
            var twobuttonklein = new Button (Activity) { LayoutParameters = new ViewGroup.LayoutParams (FILL, WRAP) };
            twobuttonklein.Text = "Klein";
            twobuttonklein.SetBackgroundResource (Resource.Drawable.kleingrootbutton);
            var twobuttongroot = new Button(Activity){ LayoutParameters = new ViewGroup.LayoutParams (FILL, WRAP) };
            twobuttongroot.Text = "Middel/groot";
            twobuttongroot.SetBackgroundResource (Resource.Drawable.kleingrootbutton);
            twobuttonlayer.AddView (twobuttonklein);
            twobuttonlayer.AddView (twobuttongroot);
            layout.AddView (twobuttonlayer);

            var zoekvak = new EditText (Activity) { LayoutParameters = new ViewGroup.LayoutParams (FILL, WRAP) };
            zoekvak.Hint = "Zoek in inhoudsopgave";
            layout.AddView (zoekvak);

            var emptytext = new TextView (Activity) { LayoutParameters = new ViewGroup.LayoutParams (FILL, WRAP),
                Text = "Er zijn geen resultaten." };
            emptytext.SetBackgroundColor (Color.ParseColor ("#BBAA00"));
            layout.AddView (emptytext);

            var listadapter = new BindableExpandableListAdapter(this.Activity, (IMvxBindingContext) BindingContext);

            var list = new BindableExpandableListView (Activity, null, listadapter) { LayoutParameters = new ViewGroup.LayoutParams (FILL, FILL) };
            list.SetMinimumHeight (50);
            list.ItemTemplateId = Resource.Layout.indextocsectionlistitem;
            list.GroupTemplateId = Resource.Layout.indextocitem;
            list.SetGroupIndicator (null);
            list.SetBackgroundColor (Color.ParseColor ("#AAAA00"));
            layout.AddView (list);
            this.DoBind += () => {
                var bs = this.CreateBindingSet<IndexTocFragment, IndexTocViewModel> ();

                if (ViewModel == null) { 
                    Console.WriteLine ("ERROR ViewModel not set"); 
                }
                if (BindingContext == null) { 
                    Console.WriteLine ("ERROR BindingContext not set"); 
                }

                bs.Bind (title).For (x => x.Text).To (vm => vm.IndexTitle);
                // the following title displays some data from the ViewMode, and that works OK.
                                    Console.WriteLine("Index title value: "+ViewModel.IndexTitle);
                bs.Bind (twobuttongroot).For ("Click").To (vm => vm.SwitchKleinGrootCommand);
                bs.Bind (twobuttonklein).For ("Click").To (vm => vm.SwitchKleinGrootCommand);
                bs.Bind (zoekvak).For (x => x.Text).To (vm => vm.SearchText);
                bs.Bind (emptytext).For (x => x.Text).To (vm => vm.TextForEmptyList);
                bs.Bind (listadapter).For(x => x.ItemsSource).To(vm => vm.Chapters);
                bs.Apply ();                
            };
                            // the next binding was never called
            //this.DelayBind (() => {
            //
            //});

        }



        //var view = this.BindingInflate(Resource.Layout.IndexTocView, null);
        Console.WriteLine ("LAYOUT RETURNED");

        return layout;
    }

    private Action DoBind;


    public override void OnResume()
    {
        // doing the binding here to make sure everything should have been set,
        but it is of course not the logical location
        base.OnResume();
        Console.WriteLine ("RESUMING");
        if (DoBind != null)
            DoBind ();

    }



}

现在我将创建一个包含我需要的所有内容的片段布局,并隐藏不需要的元素,这可能会起作用。但我希望我可以使用从代码创建视图。

感谢您的帮助。

顺便说一句:来自活动和演示者的代码是从 MvvmCross 中的片段示例中获取的自定义演示者代码。Android 代码中的绑定:Android 的MVVMCross - 如何在代码中进行绑定? 在堆栈上推送上下文:MvvmCross:如何使用自定义适配器以编程方式构造 MvxListView?

4

1 回答 1

2

解决了

叹。在经历了数小时的挫折之后终于在这里问了几分钟后,这种情况已经不是第一次发生了。

解决了它(至少它现在正在工作):

        BindingContext = new MvxAndroidBindingContext (Activity, new MvxSimpleLayoutInflater(inflater), ViewModel);

在我的代码中,没有提供最后一个参数。所以可能绑定上下文没有完全设置。

在 MvvmCross 代码中,我发现了一些关于 EnsureBindingContext 不起作用的警告......

现在测试延迟绑定是否再次工作......

于 2013-09-14T06:49:48.517 回答