Xamarin MvvmCross MvxAppCompatDialogFragment loose

2019-08-27 17:37发布

问题:

I've been using MvxAppCompatActivity throughout my project, but in this specific case I have to make use of a MvxAppCompatDialogFragment.

Unfortunately, in this case I lose the binding context of the ViewModel somehow.

MobileTestView

[MvxDialogFragmentPresentation]
[Register(nameof(MobileScreenTestView))]
public class MobileTestView : MvxAppCompatDialogFragment<MobileTestViewModel>
...
    public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        return inflater.Inflate(Resource.Layout.mobile_screen, container, false);
    }
...

MobileTestViewModel

public class MobileTestViewModel : MvxViewModel<MInput, MResult>
...
public string Instructions { get; set; } = "Instructions";
...

mobile_screen.axml

...
<TextView
    android:id="@+id/text_mobile"
    android:layout_width="match_parent"
    android:layout_height="44dp"
    android:layout_alignParentBottom="true"
    android:layout_centerHorizontal="true"
    android:gravity="center_vertical|center_horizontal"
    tools:text="Scan"
    local:MvxBind="Text Instructions" />
...

local:MvxBind="Text Instructions" does not work anymore, but I've checked and it is set in the view model before it gets to OnCreateView().

The above code would work fine for a MvxAppCompatActivity.

If what I'm trying to do is not possible, I can always do it like

view.FindViewById<TextView>(Resource.Id.text_mobile).Text = ViewModel.Instructions;

It's not that I really need to use local:MvxBind, but I would like to know what I'm doing wrong.

Update - For anyone having the same problem:

Change the OnCreateView method to:

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

    return this.BindingInflate(Resource.Layout.mobile_screen, container, false);
}

and your BindingContext will work fine.

回答1:

As you noticed yourself, you had to use this.BindingInflate instead of the LayoutInflater argument in OnCreateView. This is because we have no way to intercept the Fragment lifecycle in MvvmCross to provide our own Layout Inflater.

What BindingInflate does, is to run through the view hierarchy and look for all the custom attributes applied on views, in your case Text Instructions and apply these bindings between the View and the ViewModel.

So whenever working with Fragments, you should use BindingInflate.